• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2016 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 re
7import os
8
9from autotest_lib.client.common_lib import error
10from autotest_lib.client.common_lib import utils
11from autotest_lib.server.cros.faft.firmware_test import FirmwareTest
12
13
14class platform_Flashrom(FirmwareTest):
15    """
16    Test flashrom works correctly by calling
17    chromeos-firmwareupdate --mode=factory.
18    """
19    version = 1
20
21
22    def initialize(self, host, cmdline_args):
23        # This test assume the system already have the latest RW from
24        # shellball.  If you not sure, run chromeos-firmware --mode=factory.
25        # Device should have WP disable.
26
27        # Parse arguments from command line
28        dict_args = utils.args_to_dict(cmdline_args)
29        super(platform_Flashrom, self).initialize(host, cmdline_args)
30
31    def run_cmd(self, command, checkfor=''):
32        """
33        Log and execute command and return the output.
34
35        @param command: Command to execute on device.
36        @param checkfor: If not emmpty, fail test if checkfor not in output.
37        @returns the output of command.
38        """
39        command = command + ' 2>&1'
40        logging.info('Execute %s', command)
41        output = self.faft_client.system.run_shell_command_get_output(command)
42        logging.info('Output >>> %s <<<', output)
43        if checkfor and checkfor not in '\n'.join(output):
44            raise error.TestFail('Expect %s in output of %s' %
45                                 (checkfor, '\n'.join(output)))
46        return output
47
48    def _check_wp_disable(self):
49        """Check firmware is write protect disabled."""
50        self.run_cmd('flashrom -p host --wp-status', checkfor='is disabled')
51        if self.faft_config.chrome_ec:
52            self.run_cmd('flashrom -p ec --wp-status', checkfor='is disabled')
53        if self.faft_config.chrome_usbpd:
54            self.run_cmd('flashrom -p ec:dev=1 --wp-status',
55                         checkfor='is disabled')
56
57    def _get_eeprom(self, fmap):
58        """Get fmap start and size.
59
60        @return tuple for start and size for fmap.
61        """
62        # $ mosys eeprom map | grep RW_SECTION_B
63        # host_firmware | RW_SECTION_B | 0x005f0000 | 0x003f0000 | static
64        output = self.run_cmd('mosys eeprom map | grep %s' % fmap)
65        fmap_data = map(lambda s:s.strip(), output[0].split('|'))
66        logging.info('fmap %s', fmap_data)
67        return (int(fmap_data[2], 16), int(fmap_data[3], 16))
68
69    def run_once(self, dev_mode=True):
70        # 1) Check SW WP is disabled.
71        self._check_wp_disable()
72
73        # Output location on DUT.
74        # Set if you want to preserve output content for debug.
75        tmpdir = os.getenv('DUT_TMPDIR')
76        if not tmpdir: tmpdir = '/tmp'
77
78        # 2) Erase RW section B.  Needed CL 329549 starting with R51-7989.0.0.
79        # before this change -E erase everything.
80        self.run_cmd('flashrom -E -i RW_SECTION_B', 'SUCCESS')
81
82        # 3) Reinstall RW B (Test flashrom)
83        self.run_cmd('chromeos-firmwareupdate --mode=factory',
84                     '(factory_install) completed.')
85
86        # 4) Check that device can be rebooted.
87        self.switcher.mode_aware_reboot()
88
89        # 5) Compare flash section B vs shellball section B
90        # 5.1) Extract shellball RW section B.
91        outdir = self.run_cmd('chromeos-firmwareupdate --sb_extract')[-1]
92        shball_path = outdir.split()[-1]
93        shball_bios = os.path.join(shball_path, 'bios.bin')
94        shball_rw_b = os.path.join(shball_path, 'shball_rw_b.bin')
95
96        # Extract RW B, offset detail
97        # Figure out section B start byte and size.
98        (Bstart, Blen) = self._get_eeprom('RW_SECTION_B')
99        self.run_cmd('dd bs=1 skip=%d count=%d if=%s of=%s 2>&1'
100                     % (Bstart, Blen, shball_bios, shball_rw_b), '%d bytes' % Blen)
101
102        # 5.2) Extract flash RW section B.
103        # skylake cannot read only section B, see http://crosbug.com/p/52061
104        rw_b2 = os.path.join(tmpdir, 'rw_b2.bin')
105        self.run_cmd('flashrom -r -i RW_SECTION_B:%s' % rw_b2, 'SUCCESS')
106
107        # 5.3) Compare output of 5.1 vs 5.2
108        result_output = self.run_cmd('cmp %s %s' % (shball_rw_b, rw_b2))
109        logging.info('cmp %s %s == %s', shball_rw_b, rw_b2, result_output)
110
111        # 6) Report result.
112        if ''.join(result_output) != '':
113            raise error.TestFail('Mismatch between %s and %s' % (shball_rw_b, rw_b2))
114