usbpd_GFU.py revision ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43
1ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch# Copyright (c) 2015 The Chromium OS Authors. All rights reserved. 2ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch# Use of this source code is governed by a BSD-style license that can be 3ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch# found in the LICENSE file. 4ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch 5ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Brochimport collections 6ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Brochimport glob 7ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Brochimport logging 8ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Brochimport re 9ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Brochimport time 10ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch 11ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Brochfrom autotest_lib.client.bin import test 12ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Brochfrom autotest_lib.client.common_lib import error, utils 13ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Brochfrom autotest_lib.client.cros import ec as cros_ec, cros_logging 14ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch 15ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch 16ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Brochclass usbpd_GFU(test.test): 17ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch """Integration test for USB-PD Google Firmware Update (GFU). 18ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch 19ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch Test should: 20ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch - interrogate what firmware's are available for each device and for each: 21ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch 1. Use ectool's flashpd to write RW with that to mimic old hw 22ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch - Validate that kernel driver successfully updates to latest RW. 23ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch 2. Erase RW and see update as well. 24ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch 25ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch TODO: 26ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch 3. Check that update is checked after S2R. 27ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch """ 28ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch 29ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch version = 1 30ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch 31ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch FW_PATH = '/lib/firmware/cros-pd' 32ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch # <device>_v<major>.<minor>.<build>-<commit SHA> 33ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch FW_NAME_RE = r'%s/(\w+)_v(\d+)\.(\d+)\.(\d+)-([0-9a-f]+).*' % (FW_PATH) 34ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch GOOGLE_VID = '0x18d1' 35ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch MAX_UPDATE_SECS = 80 36ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch FW_UP_DNAME = 'cros_ec_pd_update' 37ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch # TODO(tbroch) This will be change once cros_ec_pd_update is abstracted from 38ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch # ACPI driver. Will need to fix this once it happens. 39ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch FW_UP_DISABLE_PATH = '/sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:1e/PNP0C09:00/GOOG0003:00/disable' 40ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch 41ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch # TODO(tbroch) find better way to build this or we'll have to edit test for 42ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch # each new PD peripheral. 43ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch DEV_MAJOR = dict(zinger=1, minimuffin=2, dingdong=3, hoho=4) 44ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch 45ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch def _index_firmware_avail(self): 46ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch """Index the various USB-PD firmwares in the rootfs. 47ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch 48ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch TODO(crosbug.com/434522) This method will need reworked after we've come 49ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch up with a better method for firmware release. 50ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch 51ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch @returns: dictionary of firmwares (key == name, value == list of 52ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch firmware paths) 53ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch """ 54ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch fw_dict = collections.defaultdict(list) 55ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch for fw in glob.glob('%s/*_v[1-9].*.bin' % (self.FW_PATH)): 56ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch mat = re.match(self.FW_NAME_RE, fw) 57ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch if not mat: 58ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch continue 59ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch 60ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch name = mat.group(1) 61ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch fw_dict[name].append(fw) 62ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch 63ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch return fw_dict 64ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch 65ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch def _is_gfu(self, port): 66ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch """Is it in GFU? 67ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch 68ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch @param port: EC_USBPD object for port. 69ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch 70ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch @returns: True if GFU enterd, False otherwise. 71ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch """ 72ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch return port.is_amode_supported(self.GOOGLE_VID) 73ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch 74ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch def _is_in_rw(self, port): 75ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch """Is PD device in RW firmware? 76ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch 77ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch @param port: EC_USBPD object for port. 78ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch 79ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch @returns: True if in RW, False otherwise. 80ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch """ 81ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch flash_info = port.get_flash_info() 82ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch logging.debug('flash_info = %s', flash_info) 83ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch return flash_info['image_status'] == 'RW' 84ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch 85ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch def _set_kernel_fw_update(self, disable=0): 86ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch """Disable the FW update driver. 87ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch 88ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch @param disable: 1 for disable, 0 for enable. 89ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch """ 90ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch utils.write_one_line(self.FW_UP_DISABLE_PATH, disable) 91ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch if not disable: 92ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch # Allow kernel driver time quiesce 93ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch time.sleep(2) 94ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch 95ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch def _modify_rw(self, port, rw=None, tries=3): 96ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch """Modify RW of USB-PD device in <port>. 97ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch 98ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch @param port: EC_USBPD object for port. 99ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch @param rw: Path to RW FW to write using ectool. If None then uses 100ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch /dev/null to invalidate the RW. 101ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch @param tries: Number of tries to update RW via flashpd 102ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch 103ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch @returns: True if success, False otherwise. 104ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch """ 105ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch timeout = self.MAX_UPDATE_SECS 106ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch 107ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch if not rw: 108ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch rw = '/dev/null' 109ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch tries = 1 110ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch 111ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch self._set_kernel_fw_update(disable=1) 112ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch 113ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch while (tries): 114ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch try: 115ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch # Note in flashpd <dev_major> <port> <file> the dev_major is 116ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch # unnecessary in all cases so its just been set to 0 117ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch port.ec_command('flashpd 0 %d %s' % (port.index, rw), 118ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch ignore_status=True, timeout=timeout) 119ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch 120ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch except error.CmdTimeoutError: 121ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch # TODO(tbroch) could remove try/except if ec_command used run 122ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch # instead of system_output + ignore_timeout=True 123ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch tries -= 1 124ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch continue 125ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch 126ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch if rw != '/dev/null' and not self._is_in_rw(port): 127ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch logging.warn('Port%d: not in RW after flashpd ... retrying', 128ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch port.index) 129ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch tries -= 1 130ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch else: 131ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch break 132ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch 133ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch self._set_kernel_fw_update() 134ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch 135ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch msg = self._reader.get_last_msg([r'%s.*is in RO' % port.index, 136ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch self.FW_UP_DNAME], 137ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch retries=5, sleep_seconds=2) 138ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch if not msg: 139ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch logging.warn('Port%d: Driver does NOT see dev in not in RO', 140ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch port.index) 141ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch return False 142ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch logging.info('Port%d: Driver sees device in RO', port.index) 143ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch return True 144ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch 145ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch def _test_update(self, port, rw=None, tries=3): 146ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch """Test RW update. 147ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch 148ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch Method tests the kernel's RW update process by first modifying the 149ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch existing RW (either invalidating or rolling it back) via ectool. It 150ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch then querys the syslog to validate kernel sees the need for update and 151ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch is successful. 152ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch 153ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch @param port: EC_USBPD object for port. 154ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch @param rw: path to RW firmware to write via ectool to test upgrade. 155ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch @param tries: integer number of attempts to write RW. Necessary as 156ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch update is not robust (design decision). 157ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch """ 158ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch if not tries: 159ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch raise error.TestError('Retries must be > 0') 160ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch 161ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch if not self._is_in_rw(port): 162ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch raise error.TestError('Port%d: Device is not in RW' % port.index) 163ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch 164ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch fw_up_re = r'%s.*Port%d FW update completed' % (self.FW_UP_DNAME, 165ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch port.index) 166ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch 167ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch while tries: 168ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch self._reader.set_start_by_current() 169ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch rsp = self._modify_rw(port, rw) 170ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch 171ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch if not rsp: 172ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch rsp_str = 'Port%d: RW modified with RW=%s failed' % \ 173ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch (port.index, rw) 174ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch if tries: 175ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch logging.warn('%s ... retrying.', rsp_str) 176ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch tries -= 1 177ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch else: 178ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch raise error.TestError(rsp_str) 179ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch 180ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch self._reader.set_start_by_current() 181ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch msg = self._reader.get_last_msg([fw_up_re], 182ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch retries=(self.MAX_UPDATE_SECS / 2), 183ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch sleep_seconds=2) 184ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch 185ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch if not msg: 186ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch rsp_str = 'Port%d: driver did NOT update FW' % port.index 187ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch if tries: 188ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch logging.warn('%s ... retrying.', rsp_str) 189ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch tries -= 1 190ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch continue 191ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch else: 192ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch raise error.TestError(rsp_str) 193ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch 194ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch logging.info('Port%d: Driver completed RW update', port.index) 195ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch 196ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch # Allow adequate reboot time after RW write completes and device is 197ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch # rebooted. 198ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch time.sleep(3) 199ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch 200ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch if not self._is_in_rw(port): 201ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch rsp_str = 'Port%d: Device is not in RW' % port.index 202ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch if tries: 203ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch logging.warn('%s ... retrying.', rsp_str) 204ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch tries -= 1 205ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch continue 206ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch else: 207ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch raise error.TestError(rsp_str) 208ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch 209ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch break # success # 210ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch 211ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch def _test_rw_rollback(self, port, fw_dict): 212ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch """Test rolling back RW firmware. 213ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch 214ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch @param port: EC_USBPD object for port. 215ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch @param fw_dict: dictionary of firmwares. 216ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch """ 217ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch self._set_kernel_fw_update() 218ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch 219ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch # test old RW update 220ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch flash_info = port.get_flash_info() 221ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch for dev_name in fw_dict.keys(): 222ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch if flash_info['dev_major'] == self.DEV_MAJOR[dev_name]: 223ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch for old_rw in sorted(fw_dict[dev_name], reverse=True)[1:]: 224ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch logging.info('Port%d: Rollback test %s to %s', 225ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch port.index, dev_name, old_rw) 226ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch self._test_update(port, rw=old_rw) 227ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch break 228ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch 229ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch def _test_ro_only(self, port, ro_reps): 230ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch """Test FW update on device with RO only. 231ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch 232ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch @param port: EC_USBPD object for port. 233ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch @param ro_reps: Number of times to repeat test. 234ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch """ 235ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch # test update in RO ro_reps times 236ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch for i in xrange(ro_reps): 237ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch logging.info('RO Loop%d', i) 238ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch self._test_update(port) 239ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch 240ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch def run_once(self, ro_reps=1): 241ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch 242ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch fw_dict = self._index_firmware_avail() 243ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch 244ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch self._usbpd = cros_ec.EC_USBPD() 245ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch self._reader = cros_logging.LogReader() 246ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch 247ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch for port in self._usbpd.ports: 248ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch if not port.is_dfp(): 249ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch continue 250ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch 251ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch logging.info('Port%d: is a DFP', port.index) 252ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch 253ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch if not self._is_gfu(port): 254ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch continue 255ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch 256ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch logging.info('Port%d: supports GFU', port.index) 257ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch 258ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch self._test_rw_rollback(port, fw_dict) 259ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch self._test_ro_only(port, ro_reps) 260ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch 261ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch def cleanup(self): 262ee1ba32ea5ba3bb84c1ed040dbc9a2976edcef43Todd Broch self._set_kernel_fw_update() 263