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