blob: fdfbe5335b29fec121c7cbc0ffc8b0292867c0d7 [file] [log] [blame]
Tom Wai-Hong Tama70f0fe2011-09-02 18:28:47 +08001# Copyright (c) 2011 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
Tom Wai-Hong Tamfda76e22012-08-08 17:19:10 +08005import ctypes
Tom Wai-Hong Tama70f0fe2011-09-02 18:28:47 +08006import logging
Tom Wai-Hong Tam76c75072011-10-25 18:00:12 +08007import os
Tom Wai-Hong Tama70f0fe2011-09-02 18:28:47 +08008import re
Tom Wai-Hong Tame796de42012-10-16 19:42:20 +08009import subprocess
Tom Wai-Hong Tam40fd9472012-01-09 17:11:02 +080010import sys
Tom Wai-Hong Tama70f0fe2011-09-02 18:28:47 +080011import time
Tom Wai-Hong Tama70f0fe2011-09-02 18:28:47 +080012
Tom Wai-Hong Tam76c75072011-10-25 18:00:12 +080013from autotest_lib.client.bin import utils
Tom Wai-Hong Tama70f0fe2011-09-02 18:28:47 +080014from autotest_lib.client.common_lib import error
Tom Wai-Hong Tam6ec46e32012-10-05 16:39:21 +080015from autotest_lib.server.cros import vboot_constants as vboot
Tom Wai-Hong Tam665281c2012-10-30 11:55:10 +080016from autotest_lib.server.cros import chrome_ec
Vic Yangf93f7022012-10-31 09:40:36 +080017from autotest_lib.server.cros.faft_checkers import FAFTCheckers
Vic Yangebd6de62012-06-26 14:25:57 +080018from autotest_lib.server.cros.faft_client_attribute import FAFTClientAttribute
Tom Wai-Hong Tam41738762012-10-29 14:32:39 +080019from autotest_lib.server.cros.faft_delay_constants import FAFTDelayConstants
Tom Wai-Hong Tam22b77302011-11-03 13:03:48 +080020from autotest_lib.server.cros.servo_test import ServoTest
Gediminas Ramanauskasba352ad2012-11-09 09:43:32 -080021from autotest_lib.server import hosts
Tom Wai-Hong Tam40fd9472012-01-09 17:11:02 +080022from autotest_lib.site_utils import lab_test
Tom Wai-Hong Tam08885ae2012-10-19 17:16:45 +080023from autotest_lib.site_utils.chromeos_test.common_util import ChromeOSTestError
Tom Wai-Hong Tama70f0fe2011-09-02 18:28:47 +080024
Tom Wai-Hong Tama70f0fe2011-09-02 18:28:47 +080025class FAFTSequence(ServoTest):
26 """
27 The base class of Fully Automated Firmware Test Sequence.
28
29 Many firmware tests require several reboot cycles and verify the resulted
30 system states. To do that, an Autotest test case should detailly handle
31 every action on each step. It makes the test case hard to read and many
32 duplicated code. The base class FAFTSequence is to solve this problem.
33
34 The actions of one reboot cycle is defined in a dict, namely FAFT_STEP.
35 There are four functions in the FAFT_STEP dict:
36 state_checker: a function to check the current is valid or not,
37 returning True if valid, otherwise, False to break the whole
38 test sequence.
39 userspace_action: a function to describe the action ran in userspace.
Tom Wai-Hong Tamb21b6b42012-07-26 10:46:30 +080040 reboot_action: a function to do reboot, default: sync_and_warm_reboot.
Tom Wai-Hong Tama70f0fe2011-09-02 18:28:47 +080041 firmware_action: a function to describe the action ran after reboot.
42
Tom Wai-Hong Tam7c17ff22011-10-26 09:44:09 +080043 And configurations:
44 install_deps_after_boot: if True, install the Autotest dependency after
45 boot; otherwise, do nothing. It is for the cases of recovery mode
46 test. The test boots a USB/SD image instead of an internal image.
47 The previous installed Autotest dependency on the internal image
48 is lost. So need to install it again.
49
Tom Wai-Hong Tama70f0fe2011-09-02 18:28:47 +080050 The default FAFT_STEP checks nothing in state_checker and does nothing in
Tom Wai-Hong Tamf1e34972011-11-02 17:07:04 +080051 userspace_action and firmware_action. Its reboot_action is a hardware
52 reboot. You can change the default FAFT_STEP by calling
Tom Wai-Hong Tama70f0fe2011-09-02 18:28:47 +080053 self.register_faft_template(FAFT_STEP).
54
55 A FAFT test case consists of several FAFT_STEP's, namely FAFT_SEQUENCE.
56 FAFT_SEQUENCE is an array of FAFT_STEP's. Any missing fields on FAFT_STEP
57 fall back to default.
58
59 In the run_once(), it should register and run FAFT_SEQUENCE like:
60 def run_once(self):
61 self.register_faft_sequence(FAFT_SEQUENCE)
62 self.run_faft_sequnce()
63
64 Note that in the last step, we only run state_checker. The
65 userspace_action, reboot_action, and firmware_action are not executed.
66
67 Attributes:
68 _faft_template: The default FAFT_STEP of each step. The actions would
69 be over-written if the registered FAFT_SEQUENCE is valid.
70 _faft_sequence: The registered FAFT_SEQUENCE.
Tom Wai-Hong Tame796de42012-10-16 19:42:20 +080071 _install_image_path: The URL or the path on the host to the Chrome OS
72 test image to be installed.
Tom Wai-Hong Tam1a3ff742012-01-11 16:36:46 +080073 _firmware_update: Boolean. True if firmware update needed after
74 installing the image.
Tom Wai-Hong Tama70f0fe2011-09-02 18:28:47 +080075 """
76 version = 1
77
Tom Wai-Hong Tamcfda61f2011-11-02 17:41:01 +080078 # Mapping of partition number of kernel and rootfs.
79 KERNEL_MAP = {'a':'2', 'b':'4', '2':'2', '4':'4', '3':'2', '5':'4'}
80 ROOTFS_MAP = {'a':'3', 'b':'5', '2':'3', '4':'5', '3':'3', '5':'5'}
81 OTHER_KERNEL_MAP = {'a':'4', 'b':'2', '2':'4', '4':'2', '3':'4', '5':'2'}
82 OTHER_ROOTFS_MAP = {'a':'5', 'b':'3', '2':'5', '4':'3', '3':'5', '5':'3'}
83
Tom Wai-Hong Tam78709592011-12-19 11:16:50 +080084 CHROMEOS_MAGIC = "CHROMEOS"
85 CORRUPTED_MAGIC = "CORRUPTD"
86
Vadim Bendebury89ec24e2012-12-17 12:54:18 -080087 _ROOTFS_PARTITION_NUMBER = 3
88
Tom Wai-Hong Tame796de42012-10-16 19:42:20 +080089 _HTTP_PREFIX = 'http://'
90 _DEVSERVER_PORT = '8090'
91
Tom Wai-Hong Tam109f63c2011-12-08 14:58:27 +080092 _faft_template = {}
Tom Wai-Hong Tama70f0fe2011-09-02 18:28:47 +080093 _faft_sequence = ()
94
Tom Wai-Hong Tam40fd9472012-01-09 17:11:02 +080095 _install_image_path = None
Tom Wai-Hong Tam1a3ff742012-01-11 16:36:46 +080096 _firmware_update = False
Tom Wai-Hong Tam1db43832011-12-09 10:50:56 +080097
ctchang38ae4922012-09-03 17:01:16 +080098 _backup_firmware_sha = ()
99
Tom Wai-Hong Tam01d5e572012-10-23 10:07:11 +0800100 # Class level variable, keep track the states of one time setup.
101 # This variable is preserved across tests which inherit this class.
102 _global_setup_done = {
103 'gbb_flags': False,
Tom Wai-Hong Tam73229372012-10-23 11:58:16 +0800104 'reimage': False,
Tom Wai-Hong Tam01d5e572012-10-23 10:07:11 +0800105 'usb_check': False,
106 }
Vic Yang54f70572012-10-19 17:05:26 +0800107
Tom Wai-Hong Tam01d5e572012-10-23 10:07:11 +0800108 @classmethod
109 def check_setup_done(cls, label):
110 """Check if the given setup is done.
Vic Yangdbaba8f2012-10-17 16:05:35 +0800111
Tom Wai-Hong Tam01d5e572012-10-23 10:07:11 +0800112 Args:
113 label: The label of the setup.
114 """
115 return cls._global_setup_done[label]
116
117
118 @classmethod
119 def mark_setup_done(cls, label):
120 """Mark the given setup done.
121
122 Args:
123 label: The label of the setup.
124 """
125 cls._global_setup_done[label] = True
126
127
128 @classmethod
129 def unmark_setup_done(cls, label):
130 """Mark the given setup not done.
131
132 Args:
133 label: The label of the setup.
134 """
135 cls._global_setup_done[label] = False
Vic Yang54f70572012-10-19 17:05:26 +0800136
Tom Wai-Hong Tam1db43832011-12-09 10:50:56 +0800137
138 def initialize(self, host, cmdline_args, use_pyauto=False, use_faft=False):
139 # Parse arguments from command line
140 args = {}
141 for arg in cmdline_args:
142 match = re.search("^(\w+)=(.+)", arg)
143 if match:
144 args[match.group(1)] = match.group(2)
Tom Wai-Hong Tam40fd9472012-01-09 17:11:02 +0800145 if 'image' in args:
146 self._install_image_path = args['image']
Vic Yang772df8a2012-10-31 10:10:49 +0800147 logging.info('Install Chrome OS test image path: %s',
Tom Wai-Hong Tam40fd9472012-01-09 17:11:02 +0800148 self._install_image_path)
Tom Wai-Hong Tam1a3ff742012-01-11 16:36:46 +0800149 if 'firmware_update' in args and args['firmware_update'].lower() \
150 not in ('0', 'false', 'no'):
151 if self._install_image_path:
152 self._firmware_update = True
153 logging.info('Also update firmware after installing.')
154 else:
155 logging.warning('Firmware update will not not performed '
156 'since no image is specified.')
Tom Wai-Hong Tam1db43832011-12-09 10:50:56 +0800157
158 super(FAFTSequence, self).initialize(host, cmdline_args, use_pyauto,
159 use_faft)
Vic Yangebd6de62012-06-26 14:25:57 +0800160 if use_faft:
161 self.client_attr = FAFTClientAttribute(
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800162 self.faft_client.system.get_platform_name())
Tom Wai-Hong Tam41738762012-10-29 14:32:39 +0800163 self.delay = FAFTDelayConstants(
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800164 self.faft_client.system.get_platform_name())
Vic Yangf93f7022012-10-31 09:40:36 +0800165 self.checkers = FAFTCheckers(self, self.faft_client)
Tom Wai-Hong Tam1db43832011-12-09 10:50:56 +0800166
Tom Wai-Hong Tam6019a1a2012-10-12 14:03:34 +0800167 if self.client_attr.chrome_ec:
Tom Wai-Hong Tam665281c2012-10-30 11:55:10 +0800168 self.ec = chrome_ec.ChromeEC(self.servo)
Tom Wai-Hong Tam6019a1a2012-10-12 14:03:34 +0800169
Tom Wai-Hong Tam9c15b4b2012-10-29 17:59:26 +0800170 if not self.client_attr.has_keyboard:
171 # The environment variable USBKM232_UART_DEVICE should point
172 # to the USB-KM232 UART device.
173 if ('USBKM232_UART_DEVICE' not in os.environ or
174 not os.path.exists(os.environ['USBKM232_UART_DEVICE'])):
175 raise error.TestError('Must set a valid environment '
176 'variable USBKM232_UART_DEVICE.')
177
Gediminas Ramanauskas3297d4f2012-09-10 15:30:10 -0700178 # Setting up key matrix mapping
179 self.servo.set_key_matrix(self.client_attr.key_matrix_layout)
180
Tom Wai-Hong Tamc5c14ef2012-11-20 16:33:37 +0800181 self._host = None
182 if (self.client_attr.broken_rec_mode and
183 self.servo.get_target_hostname()):
184 self._host = hosts.create_host(self.servo.get_target_hostname())
Gediminas Ramanauskasba352ad2012-11-09 09:43:32 -0800185
Tom Wai-Hong Tama70f0fe2011-09-02 18:28:47 +0800186
Tom Wai-Hong Tam700c9fd2012-11-15 18:18:30 +0800187 def setup(self, ec_wp=None):
Tom Wai-Hong Tama70f0fe2011-09-02 18:28:47 +0800188 """Autotest setup function."""
189 super(FAFTSequence, self).setup()
190 if not self._remote_infos['faft']['used']:
191 raise error.TestError('The use_faft flag should be enabled.')
192 self.register_faft_template({
193 'state_checker': (None),
194 'userspace_action': (None),
Tom Wai-Hong Tamb21b6b42012-07-26 10:46:30 +0800195 'reboot_action': (self.sync_and_warm_reboot),
Tom Wai-Hong Tama70f0fe2011-09-02 18:28:47 +0800196 'firmware_action': (None)
197 })
Tom Wai-Hong Tam19ad9682012-10-24 09:33:42 +0800198 self.install_test_image(self._install_image_path, self._firmware_update)
Tom Wai-Hong Tamb92669c2012-11-29 13:57:11 +0800199 self.record_system_info()
Tom Wai-Hong Tam01d5e572012-10-23 10:07:11 +0800200 self.setup_gbb_flags()
Tom Wai-Hong Tam700c9fd2012-11-15 18:18:30 +0800201 self.setup_ec_write_protect(ec_wp)
Tom Wai-Hong Tama70f0fe2011-09-02 18:28:47 +0800202
203
204 def cleanup(self):
205 """Autotest cleanup function."""
Tom Wai-Hong Tam700c9fd2012-11-15 18:18:30 +0800206 self.restore_ec_write_protect()
Tom Wai-Hong Tama70f0fe2011-09-02 18:28:47 +0800207 self._faft_sequence = ()
Tom Wai-Hong Tam109f63c2011-12-08 14:58:27 +0800208 self._faft_template = {}
Tom Wai-Hong Tama70f0fe2011-09-02 18:28:47 +0800209 super(FAFTSequence, self).cleanup()
210
211
Tom Wai-Hong Tamb92669c2012-11-29 13:57:11 +0800212 def record_system_info(self):
213 """Record some critical system info to the attr keyval.
214
215 This info is used by generate_test_report and local_dash later.
216 """
217 self.write_attr_keyval({
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800218 'fw_version': self.faft_client.ec.get_version(),
219 'hwid': self.faft_client.system.get_crossystem_value('hwid'),
220 'fwid': self.faft_client.system.get_crossystem_value('fwid'),
Tom Wai-Hong Tamb92669c2012-11-29 13:57:11 +0800221 })
222
223
Tom Wai-Hong Tam01d5e572012-10-23 10:07:11 +0800224 def invalidate_firmware_setup(self):
225 """Invalidate all firmware related setup state.
Vic Yangdbaba8f2012-10-17 16:05:35 +0800226
Tom Wai-Hong Tam01d5e572012-10-23 10:07:11 +0800227 This method is called when the firmware is re-flashed. It resets all
228 firmware related setup states so that the next test setup properly
229 again.
Vic Yangdbaba8f2012-10-17 16:05:35 +0800230 """
Tom Wai-Hong Tam01d5e572012-10-23 10:07:11 +0800231 self.unmark_setup_done('gbb_flags')
Vic Yangdbaba8f2012-10-17 16:05:35 +0800232
233
Tom Wai-Hong Tamc285f4c2012-10-30 15:44:39 +0800234 def _retrieve_recovery_reason_from_trap(self):
235 """Try to retrieve the recovery reason from a trapped recovery screen.
Tom Wai-Hong Tame6232342012-09-24 16:18:01 +0800236
Tom Wai-Hong Tamc285f4c2012-10-30 15:44:39 +0800237 Returns:
238 The recovery_reason, 0 if any error.
Tom Wai-Hong Tame6232342012-09-24 16:18:01 +0800239 """
Tom Wai-Hong Tamc285f4c2012-10-30 15:44:39 +0800240 recovery_reason = 0
Tom Wai-Hong Tam4bb85e22012-10-25 14:35:24 +0800241 logging.info('Try to retrieve recovery reason...')
242 if self.servo.get('usb_mux_sel1') == 'dut_sees_usbkey':
243 self.wait_fw_screen_and_plug_usb()
244 else:
245 self.servo.set('usb_mux_sel1', 'dut_sees_usbkey')
246
247 try:
248 self.wait_for_client(install_deps=True)
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800249 lines = self.faft_client.system.run_shell_command_get_output(
Tom Wai-Hong Tam4bb85e22012-10-25 14:35:24 +0800250 'crossystem recovery_reason')
Tom Wai-Hong Tamc285f4c2012-10-30 15:44:39 +0800251 recovery_reason = int(lines[0])
252 logging.info('Got the recovery reason %d.', recovery_reason)
Tom Wai-Hong Tam4bb85e22012-10-25 14:35:24 +0800253 except AssertionError:
254 logging.info('Failed to get the recovery reason.')
Tom Wai-Hong Tamc285f4c2012-10-30 15:44:39 +0800255 return recovery_reason
Tom Wai-Hong Tam4bb85e22012-10-25 14:35:24 +0800256
Tom Wai-Hong Tamc285f4c2012-10-30 15:44:39 +0800257
258 def _reset_client(self):
259 """Reset client to a workable state.
260
261 This method is called when the client is not responsive. It may be
262 caused by the following cases:
263 - halt on a firmware screen without timeout, e.g. REC_INSERT screen;
264 - corrupted firmware;
265 - corrutped OS image.
266 """
Tom Wai-Hong Tame6232342012-09-24 16:18:01 +0800267 # DUT may halt on a firmware screen. Try cold reboot.
268 logging.info('Try cold reboot...')
269 self.cold_reboot()
Tom Wai-Hong Tame2f9cf92012-11-26 10:04:11 +0800270 self.wait_for_client_offline()
271 self.wait_dev_screen_and_ctrl_d()
Tom Wai-Hong Tame6232342012-09-24 16:18:01 +0800272 try:
Vic Yang8eaf5ad2012-09-13 14:05:37 +0800273 self.wait_for_client()
Tom Wai-Hong Tame6232342012-09-24 16:18:01 +0800274 return
275 except AssertionError:
276 pass
277
278 # DUT may be broken by a corrupted firmware. Restore firmware.
279 # We assume the recovery boot still works fine. Since the recovery
280 # code is in RO region and all FAFT tests don't change the RO region
281 # except GBB.
282 if self.is_firmware_saved():
Tom Wai-Hong Tamc285f4c2012-10-30 15:44:39 +0800283 self._ensure_client_in_recovery()
Tom Wai-Hong Tame6232342012-09-24 16:18:01 +0800284 logging.info('Try restore the original firmware...')
285 if self.is_firmware_changed():
286 try:
287 self.restore_firmware()
288 return
289 except AssertionError:
290 logging.info('Restoring firmware doesn\'t help.')
291
292 # DUT may be broken by a corrupted OS image. Restore OS image.
Tom Wai-Hong Tamc285f4c2012-10-30 15:44:39 +0800293 self._ensure_client_in_recovery()
Tom Wai-Hong Tame6232342012-09-24 16:18:01 +0800294 logging.info('Try restore the OS image...')
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800295 self.faft_client.system.run_shell_command('chromeos-install --yes')
Tom Wai-Hong Tame6232342012-09-24 16:18:01 +0800296 self.sync_and_warm_reboot()
297 self.wait_for_client_offline()
Tom Wai-Hong Tame2f9cf92012-11-26 10:04:11 +0800298 self.wait_dev_screen_and_ctrl_d()
Tom Wai-Hong Tame6232342012-09-24 16:18:01 +0800299 try:
300 self.wait_for_client(install_deps=True)
301 logging.info('Successfully restore OS image.')
302 return
303 except AssertionError:
304 logging.info('Restoring OS image doesn\'t help.')
305
306
Tom Wai-Hong Tamc285f4c2012-10-30 15:44:39 +0800307 def _ensure_client_in_recovery(self):
Tom Wai-Hong Tame6232342012-09-24 16:18:01 +0800308 """Ensure client in recovery boot; reboot into it if necessary.
309
310 Raises:
311 error.TestError: if failed to boot the USB image.
312 """
313 # DUT works fine and is already in recovery boot, done.
314 if self._ping_test(self._client.ip, timeout=5):
Vic Yangf93f7022012-10-31 09:40:36 +0800315 if self.checkers.crossystem_checker({'mainfw_type': 'recovery'}):
Tom Wai-Hong Tame6232342012-09-24 16:18:01 +0800316 return
317
318 logging.info('Try boot into USB image...')
319 self.servo.enable_usb_hub(host=True)
320 self.enable_rec_mode_and_reboot()
321 self.wait_fw_screen_and_plug_usb()
322 try:
323 self.wait_for_client(install_deps=True)
324 except AssertionError:
325 raise error.TestError('Failed to boot the USB image.')
Vic Yang8eaf5ad2012-09-13 14:05:37 +0800326
327
Tom Wai-Hong Tamc285f4c2012-10-30 15:44:39 +0800328 def _restore_routine_from_timeout(self, next_step=None):
329 """A routine to try to restore the system from a timeout error.
330
331 This method is called when FAFT failed to connect DUT after reboot.
332
333 Args:
334 next_step: Optional, a FAFT_STEP dict of the next step, which is used
335 for diagnostic.
336
337 Raises:
338 error.TestFail: This exception is already raised, with a decription
339 why it failed.
340 """
341 next_checker_matched = False
342 if next_step is not None:
343 next_test = {}
344 next_test.update(self._faft_template)
345 next_test.update(next_step)
346
347 # TODO(waihong@chromium.org): Implement replugging the Ethernet to
348 # identify if it is a network flaky.
349
350 recovery_reason = self._retrieve_recovery_reason_from_trap()
351 if next_step is not None and recovery_reason:
352 if self._call_action(next_test['state_checker']):
353 # Repluging the USB can pass the state_checker of the next step,
354 # meaning that the firmware failed to boot into USB directly.
355 next_checker_matched = True
356
357 # Reset client to a workable state.
358 self._reset_client()
359
360 # Raise the proper TestFail exception.
361 if next_checker_matched:
362 raise error.TestFail('Firmware failed to auto-boot USB in the '
Tom Wai-Hong Tam66648432012-11-07 10:06:00 +0800363 'recovery boot (reason: %d)' % recovery_reason)
Tom Wai-Hong Tamc285f4c2012-10-30 15:44:39 +0800364 elif recovery_reason:
Tom Wai-Hong Tam66648432012-11-07 10:06:00 +0800365 raise error.TestFail('Trapped in the recovery screen (reason: %d) '
366 'and timed out' % recovery_reason)
Tom Wai-Hong Tamc285f4c2012-10-30 15:44:39 +0800367 else:
Tom Wai-Hong Tam66648432012-11-07 10:06:00 +0800368 raise error.TestFail('Timed out waiting for DUT reboot')
Tom Wai-Hong Tamc285f4c2012-10-30 15:44:39 +0800369
370
Tom Wai-Hong Tama6b382c2012-11-14 09:31:02 +0800371 def assert_test_image_in_usb_disk(self, usb_dev=None, install_shim=False):
Tom Wai-Hong Tam76c75072011-10-25 18:00:12 +0800372 """Assert an USB disk plugged-in on servo and a test image inside.
373
Tom Wai-Hong Tam91f49822011-12-28 15:44:15 +0800374 Args:
375 usb_dev: A string of USB stick path on the host, like '/dev/sdc'.
376 If None, it is detected automatically.
Tom Wai-Hong Tama6b382c2012-11-14 09:31:02 +0800377 install_shim: True to verify an install shim instead of a test image.
Tom Wai-Hong Tam91f49822011-12-28 15:44:15 +0800378
Tom Wai-Hong Tam76c75072011-10-25 18:00:12 +0800379 Raises:
Tom Wai-Hong Tama6b382c2012-11-14 09:31:02 +0800380 error.TestError: if USB disk not detected or not a test (install shim)
381 image.
Tom Wai-Hong Tam76c75072011-10-25 18:00:12 +0800382 """
Tom Wai-Hong Tam01d5e572012-10-23 10:07:11 +0800383 if self.check_setup_done('usb_check'):
Vic Yang54f70572012-10-19 17:05:26 +0800384 return
Tom Wai-Hong Tam91f49822011-12-28 15:44:15 +0800385 if usb_dev:
386 assert self.servo.get('usb_mux_sel1') == 'servo_sees_usbkey'
387 else:
Vadim Bendeburycacf29f2012-07-30 17:49:11 -0700388 self.servo.enable_usb_hub(host=True)
Tom Wai-Hong Tam91f49822011-12-28 15:44:15 +0800389 usb_dev = self.servo.probe_host_usb_dev()
390 if not usb_dev:
391 raise error.TestError(
392 'An USB disk should be plugged in the servo board.')
Vadim Bendebury89ec24e2012-12-17 12:54:18 -0800393
394 rootfs = '%s%s' % (usb_dev, self._ROOTFS_PARTITION_NUMBER)
395 logging.info('usb dev is %s', usb_dev)
396 tmpd = self.servo.system_output('mktemp -d -t usbcheck.XXXX')
397 self.servo.system('mount -o ro %s %s' % (rootfs, tmpd))
398
399 if install_shim:
400 dir_list = self.servo.system_output('ls -a %s' %
401 os.path.join(tmpd, 'root'))
402 check_passed = '.factory_installer' in dir_list
403 else:
404 check_passed = self.servo.system_output(
405 'grep -i "CHROMEOS_RELEASE_DESCRIPTION=.*test" %s' %
406 os.path.join(tmpd, 'etc/lsb-release'),
407 ignore_status=True)
408 for cmd in ('umount %s' % rootfs, 'sync', 'rm -rf %s' % tmpd):
409 self.servo.system(cmd)
410
411 if not check_passed:
412 raise error.TestError(
413 'No Chrome OS %s found on the USB flash plugged into servo' %
414 'install shim' if install_shim else 'test')
415
Tom Wai-Hong Tam01d5e572012-10-23 10:07:11 +0800416 self.mark_setup_done('usb_check')
Tom Wai-Hong Tam76c75072011-10-25 18:00:12 +0800417
418
Tom Wai-Hong Tama6b382c2012-11-14 09:31:02 +0800419 def setup_usbkey(self, usbkey, host=None, install_shim=False):
Tom Wai-Hong Tam893bcc02012-11-02 16:13:34 +0800420 """Setup the USB disk for the test.
421
422 It checks the setup of USB disk and a valid ChromeOS test image inside.
423 It also muxes the USB disk to either the host or DUT by request.
424
425 Args:
426 usbkey: True if the USB disk is required for the test, False if not
427 required.
428 host: Optional, True to mux the USB disk to host, False to mux it
429 to DUT, default to do nothing.
Tom Wai-Hong Tama6b382c2012-11-14 09:31:02 +0800430 install_shim: True to verify an install shim instead of a test image.
Tom Wai-Hong Tam893bcc02012-11-02 16:13:34 +0800431 """
432 if usbkey:
Tom Wai-Hong Tama6b382c2012-11-14 09:31:02 +0800433 self.assert_test_image_in_usb_disk(install_shim=install_shim)
Tom Wai-Hong Tam893bcc02012-11-02 16:13:34 +0800434 elif host is None:
435 # USB disk is not required for the test. Better to mux it to host.
436 host = True
437
438 if host is True:
439 self.servo.set('usb_mux_sel1', 'servo_sees_usbkey')
440 elif host is False:
441 self.servo.set('usb_mux_sel1', 'dut_sees_usbkey')
442
443
Tom Wai-Hong Tame796de42012-10-16 19:42:20 +0800444 def get_server_address(self):
445 """Get the server address seen from the client.
446
447 Returns:
448 A string of the server address.
449 """
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800450 r = self.faft_client.system.run_shell_command_get_output(
451 "echo $SSH_CLIENT")
Tom Wai-Hong Tame796de42012-10-16 19:42:20 +0800452 return r[0].split()[0]
453
454
Simran Basi741b5d42012-05-18 11:27:15 -0700455 def install_test_image(self, image_path=None, firmware_update=False):
Tom Wai-Hong Tam40fd9472012-01-09 17:11:02 +0800456 """Install the test image specied by the path onto the USB and DUT disk.
457
458 The method first copies the image to USB disk and reboots into it via
Mike Truty49153d82012-08-21 22:27:30 -0500459 recovery mode. Then runs 'chromeos-install' (and possible
460 chromeos-firmwareupdate') to install it to DUT disk.
461
462 Sample command line:
463
464 run_remote_tests.sh --servo --board=daisy --remote=w.x.y.z \
465 --args="image=/tmp/chromiumos_test_image.bin firmware_update=True" \
466 server/site_tests/firmware_XXXX/control
467
468 This test requires an automated recovery to occur while simulating
469 inserting and removing the usb key from the servo. To allow this the
470 following hardware setup is required:
471 1. servo2 board connected via servoflex.
472 2. USB key inserted in the servo2.
473 3. servo2 connected to the dut via dut_hub_in in the usb 2.0 slot.
474 4. network connected via usb dongle in the dut in usb 3.0 slot.
Tom Wai-Hong Tam40fd9472012-01-09 17:11:02 +0800475
476 Args:
Tom Wai-Hong Tame796de42012-10-16 19:42:20 +0800477 image_path: An URL or a path on the host to the test image.
Tom Wai-Hong Tam1a3ff742012-01-11 16:36:46 +0800478 firmware_update: Also update the firmware after installing.
Tom Wai-Hong Tam71818d82012-10-24 14:57:43 +0800479
480 Raises:
481 error.TestError: If devserver failed to start.
Tom Wai-Hong Tam40fd9472012-01-09 17:11:02 +0800482 """
Tom Wai-Hong Tam19ad9682012-10-24 09:33:42 +0800483 if not image_path:
484 return
485
Tom Wai-Hong Tam73229372012-10-23 11:58:16 +0800486 if self.check_setup_done('reimage'):
487 return
488
Tom Wai-Hong Tame796de42012-10-16 19:42:20 +0800489 if image_path.startswith(self._HTTP_PREFIX):
490 # TODO(waihong@chromium.org): Add the check of the URL to ensure
491 # it is a test image.
492 devserver = None
493 image_url = image_path
Tom Wai-Hong Tam42f136d2012-10-26 11:11:23 +0800494 elif self.servo.is_localhost():
Tom Wai-Hong Tam42f136d2012-10-26 11:11:23 +0800495 # If servod is localhost, i.e. both servod and FAFT see the same
496 # file system, do nothing.
497 devserver = None
498 image_url = image_path
Tom Wai-Hong Tame796de42012-10-16 19:42:20 +0800499 else:
Tom Wai-Hong Tame796de42012-10-16 19:42:20 +0800500 image_dir, image_base = os.path.split(image_path)
501 logging.info('Starting devserver to serve the image...')
502 # The following stdout and stderr arguments should not be None,
503 # even we don't use them. Otherwise, the socket of devserve is
504 # created as fd 1 (as no stdout) but it still thinks stdout is fd
505 # 1 and dump the log to the socket. Wrong HTTP protocol happens.
Tom Wai-Hong Tam71818d82012-10-24 14:57:43 +0800506 devserver = subprocess.Popen(['/usr/lib/devserver/devserver.py',
Tom Wai-Hong Tame796de42012-10-16 19:42:20 +0800507 '--archive_dir=%s' % image_dir,
508 '--port=%s' % self._DEVSERVER_PORT],
509 stdout=subprocess.PIPE,
510 stderr=subprocess.PIPE)
511 image_url = '%s%s:%s/static/archive/%s' % (
512 self._HTTP_PREFIX,
513 self.get_server_address(),
514 self._DEVSERVER_PORT,
515 image_base)
516
Tom Wai-Hong Tam71818d82012-10-24 14:57:43 +0800517 # Wait devserver startup completely
Tom Wai-Hong Tam41738762012-10-29 14:32:39 +0800518 time.sleep(self.delay.devserver)
Tom Wai-Hong Tam71818d82012-10-24 14:57:43 +0800519 # devserver is a service running forever. If it is terminated,
520 # some error does happen.
521 if devserver.poll():
522 raise error.TestError('Starting devserver failed, '
523 'returning %d.' % devserver.returncode)
524
Vic Yang772df8a2012-10-31 10:10:49 +0800525 logging.info('Ask Servo to install the image from %s', image_url)
Tom Wai-Hong Tame796de42012-10-16 19:42:20 +0800526 self.servo.image_to_servo_usb(image_url)
527
Vadim Bendebury89ec24e2012-12-17 12:54:18 -0800528 self.assert_test_image_in_usb_disk()
529
Tom Wai-Hong Tame796de42012-10-16 19:42:20 +0800530 if devserver and devserver.poll() is None:
531 logging.info('Shutting down devserver...')
532 devserver.terminate()
Mike Truty49153d82012-08-21 22:27:30 -0500533
534 # DUT is powered off while imaging servo USB.
535 # Now turn it on.
536 self.servo.power_short_press()
537 self.wait_for_client()
538 self.servo.set('usb_mux_sel1', 'dut_sees_usbkey')
539
540 install_cmd = 'chromeos-install --yes'
541 if firmware_update:
542 install_cmd += ' && chromeos-firmwareupdate --mode recovery'
Tom Wai-Hong Tam1dd11592012-10-26 15:01:45 +0800543 self.backup_firmware()
Mike Truty49153d82012-08-21 22:27:30 -0500544
545 self.register_faft_sequence((
546 { # Step 1, request recovery boot
Vic Yangf93f7022012-10-31 09:40:36 +0800547 'state_checker': (self.checkers.crossystem_checker, {
Mike Truty49153d82012-08-21 22:27:30 -0500548 'mainfw_type': ('developer', 'normal'),
549 }),
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800550 'userspace_action': (
551 self.faft_client.system.request_recovery_boot),
Mike Truty49153d82012-08-21 22:27:30 -0500552 'firmware_action': self.wait_fw_screen_and_plug_usb,
553 'install_deps_after_boot': True,
554 },
555 { # Step 2, expected recovery boot
Vic Yangf93f7022012-10-31 09:40:36 +0800556 'state_checker': (self.checkers.crossystem_checker, {
Mike Truty49153d82012-08-21 22:27:30 -0500557 'mainfw_type': 'recovery',
Tom Wai-Hong Tam6ec46e32012-10-05 16:39:21 +0800558 'recovery_reason' : vboot.RECOVERY_REASON['US_TEST'],
Mike Truty49153d82012-08-21 22:27:30 -0500559 }),
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800560 'userspace_action': (self.faft_client.system.run_shell_command,
Mike Truty49153d82012-08-21 22:27:30 -0500561 install_cmd),
562 'reboot_action': self.cold_reboot,
563 'install_deps_after_boot': True,
564 },
565 { # Step 3, expected normal or developer boot (not recovery)
Vic Yangf93f7022012-10-31 09:40:36 +0800566 'state_checker': (self.checkers.crossystem_checker, {
Mike Truty49153d82012-08-21 22:27:30 -0500567 'mainfw_type': ('developer', 'normal')
568 }),
569 },
570 ))
571 self.run_faft_sequence()
Tom Wai-Hong Tam1dd11592012-10-26 15:01:45 +0800572
573 if firmware_update:
574 self.clear_saved_firmware()
575
Mike Truty49153d82012-08-21 22:27:30 -0500576 # 'Unplug' any USB keys in the servo from the dut.
Tom Wai-Hong Tam953c7742012-10-16 21:09:31 +0800577 self.servo.enable_usb_hub(host=True)
Tom Wai-Hong Tam6668b762012-10-23 11:45:36 +0800578 # Mark usb_check done so it won't check a test image in USB anymore.
579 self.mark_setup_done('usb_check')
Tom Wai-Hong Tam73229372012-10-23 11:58:16 +0800580 self.mark_setup_done('reimage')
Tom Wai-Hong Tam40fd9472012-01-09 17:11:02 +0800581
582
Tom Wai-Hong Tamfa3142e2012-08-16 11:53:58 +0800583 def clear_set_gbb_flags(self, clear_mask, set_mask):
584 """Clear and set the GBB flags in the current flashrom.
Tom Wai-Hong Tam15ce5812012-07-26 14:14:18 +0800585
586 Args:
Tom Wai-Hong Tamfa3142e2012-08-16 11:53:58 +0800587 clear_mask: A mask of flags to be cleared.
588 set_mask: A mask of flags to be set.
Tom Wai-Hong Tam15ce5812012-07-26 14:14:18 +0800589 """
Tom Wai-Hong Tamc1a569f2012-12-04 15:07:25 +0800590 gbb_flags = self.faft_client.bios.get_gbb_flags()
Tom Wai-Hong Tamfa3142e2012-08-16 11:53:58 +0800591 new_flags = gbb_flags & ctypes.c_uint32(~clear_mask).value | set_mask
592
593 if (gbb_flags != new_flags):
Vic Yang772df8a2012-10-31 10:10:49 +0800594 logging.info('Change the GBB flags from 0x%x to 0x%x.',
595 gbb_flags, new_flags)
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800596 self.faft_client.system.run_shell_command(
Tom Wai-Hong Tamfda76e22012-08-08 17:19:10 +0800597 '/usr/share/vboot/bin/set_gbb_flags.sh 0x%x' % new_flags)
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800598 self.faft_client.bios.reload()
Tom Wai-Hong Tama2481922012-08-08 17:24:42 +0800599 # If changing FORCE_DEV_SWITCH_ON flag, reboot to get a clear state
Tom Wai-Hong Tam6ec46e32012-10-05 16:39:21 +0800600 if ((gbb_flags ^ new_flags) & vboot.GBB_FLAG_FORCE_DEV_SWITCH_ON):
Tom Wai-Hong Tama2481922012-08-08 17:24:42 +0800601 self.run_faft_step({
Tom Wai-Hong Tam56977782012-11-23 16:13:28 +0800602 'firmware_action': self.wait_dev_screen_and_ctrl_d,
Tom Wai-Hong Tama2481922012-08-08 17:24:42 +0800603 })
Tom Wai-Hong Tam15ce5812012-07-26 14:14:18 +0800604
605
Vic Yang772df8a2012-10-31 10:10:49 +0800606 def check_ec_capability(self, required_cap=None, suppress_warning=False):
Vic Yang4d72cb62012-07-24 11:51:09 +0800607 """Check if current platform has required EC capabilities.
608
609 Args:
610 required_cap: A list containing required EC capabilities. Pass in
611 None to only check for presence of Chrome EC.
Tom Wai-Hong Tamb8a91392012-09-27 10:45:32 +0800612 suppress_warning: True to suppress any warning messages.
Vic Yang4d72cb62012-07-24 11:51:09 +0800613
614 Returns:
615 True if requirements are met. Otherwise, False.
616 """
617 if not self.client_attr.chrome_ec:
Tom Wai-Hong Tamb8a91392012-09-27 10:45:32 +0800618 if not suppress_warning:
619 logging.warn('Requires Chrome EC to run this test.')
Vic Yang4d72cb62012-07-24 11:51:09 +0800620 return False
621
Vic Yang772df8a2012-10-31 10:10:49 +0800622 if not required_cap:
623 return True
624
Vic Yang4d72cb62012-07-24 11:51:09 +0800625 for cap in required_cap:
626 if cap not in self.client_attr.ec_capability:
Tom Wai-Hong Tamb8a91392012-09-27 10:45:32 +0800627 if not suppress_warning:
628 logging.warn('Requires EC capability "%s" to run this '
Vic Yang772df8a2012-10-31 10:10:49 +0800629 'test.', cap)
Vic Yang4d72cb62012-07-24 11:51:09 +0800630 return False
631
632 return True
633
634
Tom Wai-Hong Tam07278c22012-02-08 16:53:00 +0800635 def check_root_part_on_non_recovery(self, part):
636 """Check the partition number of root device and on normal/dev boot.
637
638 Returns:
639 True if the root device matched and on normal/dev boot;
640 otherwise, False.
641 """
Vic Yangf93f7022012-10-31 09:40:36 +0800642 return self.checkers.root_part_checker(part) and \
643 self.checkers.crossystem_checker({
Tom Wai-Hong Tam07278c22012-02-08 16:53:00 +0800644 'mainfw_type': ('normal', 'developer'),
Tom Wai-Hong Tam07278c22012-02-08 16:53:00 +0800645 })
646
647
Tom Wai-Hong Tamf2103be2011-11-10 07:26:56 +0800648 def _join_part(self, dev, part):
649 """Return a concatenated string of device and partition number.
650
651 Args:
652 dev: A string of device, e.g.'/dev/sda'.
653 part: A string of partition number, e.g.'3'.
654
655 Returns:
656 A concatenated string of device and partition number, e.g.'/dev/sda3'.
657
658 >>> seq = FAFTSequence()
659 >>> seq._join_part('/dev/sda', '3')
660 '/dev/sda3'
661 >>> seq._join_part('/dev/mmcblk0', '2')
662 '/dev/mmcblk0p2'
663 """
664 if 'mmcblk' in dev:
665 return dev + 'p' + part
666 else:
667 return dev + part
668
669
Tom Wai-Hong Tamcfda61f2011-11-02 17:41:01 +0800670 def copy_kernel_and_rootfs(self, from_part, to_part):
671 """Copy kernel and rootfs from from_part to to_part.
672
673 Args:
674 from_part: A string of partition number to be copied from.
Tom Wai-Hong Tamf2103be2011-11-10 07:26:56 +0800675 to_part: A string of partition number to be copied to.
Tom Wai-Hong Tamcfda61f2011-11-02 17:41:01 +0800676 """
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800677 root_dev = self.faft_client.system.get_root_dev()
Vic Yang772df8a2012-10-31 10:10:49 +0800678 logging.info('Copying kernel from %s to %s. Please wait...',
Vic Yang55f31252012-11-01 17:07:54 +0800679 from_part, to_part)
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800680 self.faft_client.system.run_shell_command('dd if=%s of=%s bs=4M' %
Tom Wai-Hong Tamf2103be2011-11-10 07:26:56 +0800681 (self._join_part(root_dev, self.KERNEL_MAP[from_part]),
682 self._join_part(root_dev, self.KERNEL_MAP[to_part])))
Vic Yang772df8a2012-10-31 10:10:49 +0800683 logging.info('Copying rootfs from %s to %s. Please wait...',
Vic Yang55f31252012-11-01 17:07:54 +0800684 from_part, to_part)
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800685 self.faft_client.system.run_shell_command('dd if=%s of=%s bs=4M' %
Tom Wai-Hong Tamf2103be2011-11-10 07:26:56 +0800686 (self._join_part(root_dev, self.ROOTFS_MAP[from_part]),
687 self._join_part(root_dev, self.ROOTFS_MAP[to_part])))
Tom Wai-Hong Tamcfda61f2011-11-02 17:41:01 +0800688
689
690 def ensure_kernel_boot(self, part):
691 """Ensure the request kernel boot.
692
693 If not, it duplicates the current kernel to the requested kernel
694 and sets the requested higher priority to ensure it boot.
695
696 Args:
Tom Wai-Hong Tama9c1a502011-11-10 06:39:26 +0800697 part: A string of kernel partition number or 'a'/'b'.
Tom Wai-Hong Tamcfda61f2011-11-02 17:41:01 +0800698 """
Vic Yangf93f7022012-10-31 09:40:36 +0800699 if not self.checkers.root_part_checker(part):
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800700 if self.faft_client.kernel.diff_a_b():
Tom Wai-Hong Tam622d0ba2012-08-15 16:29:05 +0800701 self.copy_kernel_and_rootfs(
702 from_part=self.OTHER_KERNEL_MAP[part],
703 to_part=part)
Tom Wai-Hong Tamc7ecfca2011-12-06 11:12:31 +0800704 self.run_faft_step({
705 'userspace_action': (self.reset_and_prioritize_kernel, part),
706 })
Tom Wai-Hong Tamcfda61f2011-11-02 17:41:01 +0800707
708
Tom Wai-Hong Tam05574ee2012-10-30 11:34:21 +0800709 def set_hardware_write_protect(self, enable):
Vic Yang2cabf812012-08-28 02:39:04 +0800710 """Set hardware write protect pin.
711
712 Args:
713 enable: True if asserting write protect pin. Otherwise, False.
714 """
715 self.servo.set('fw_wp_vref', self.client_attr.wp_voltage)
716 self.servo.set('fw_wp_en', 'on')
Tom Wai-Hong Tam05574ee2012-10-30 11:34:21 +0800717 self.servo.set('fw_wp', 'on' if enable else 'off')
Vic Yang416f2032012-08-28 10:18:03 +0800718
719
Tom Wai-Hong Tam44204b32012-11-20 13:55:40 +0800720 def set_ec_write_protect_and_reboot(self, enable):
Vic Yang416f2032012-08-28 10:18:03 +0800721 """Set EC write protect status and reboot to take effect.
722
Tom Wai-Hong Tam44204b32012-11-20 13:55:40 +0800723 The write protect state is only activated if both hardware write
724 protect pin is asserted and software write protect flag is set.
Vic Yang416f2032012-08-28 10:18:03 +0800725 This method asserts/deasserts hardware write protect pin first, and
726 set corresponding EC software write protect flag.
727
Tom Wai-Hong Tam44204b32012-11-20 13:55:40 +0800728 If the device uses non-Chrome EC, set the software write protect via
729 flashrom.
730
731 If the device uses Chrome EC, a reboot is required for write protect
732 to take effect. Since the software write protect flag cannot be unset
733 if hardware write protect pin is asserted, we need to deasserted the
734 pin first if we are deactivating write protect. Similarly, a reboot
735 is required before we can modify the software flag.
736
Vic Yang416f2032012-08-28 10:18:03 +0800737 Args:
738 enable: True if activating EC write protect. Otherwise, False.
739 """
Tom Wai-Hong Tam05574ee2012-10-30 11:34:21 +0800740 self.set_hardware_write_protect(enable)
Tom Wai-Hong Tam44204b32012-11-20 13:55:40 +0800741 if self.client_attr.chrome_ec:
742 self.set_chrome_ec_write_protect_and_reboot(enable)
743 else:
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800744 self.faft_client.ec.set_write_protect(enable)
Tom Wai-Hong Tam44204b32012-11-20 13:55:40 +0800745 self.sync_and_warm_reboot()
746
747
748 def set_chrome_ec_write_protect_and_reboot(self, enable):
749 """Set Chrome EC write protect status and reboot to take effect.
750
751 Args:
752 enable: True if activating EC write protect. Otherwise, False.
753 """
Tom Wai-Hong Tam05574ee2012-10-30 11:34:21 +0800754 if enable:
Vic Yang416f2032012-08-28 10:18:03 +0800755 # Set write protect flag and reboot to take effect.
Tom Wai-Hong Tam05574ee2012-10-30 11:34:21 +0800756 self.ec.set_flash_write_protect(enable)
Vic Yang416f2032012-08-28 10:18:03 +0800757 self.sync_and_ec_reboot()
758 else:
759 # Reboot after deasserting hardware write protect pin to deactivate
760 # write protect. And then remove software write protect flag.
761 self.sync_and_ec_reboot()
Tom Wai-Hong Tam05574ee2012-10-30 11:34:21 +0800762 self.ec.set_flash_write_protect(enable)
Vic Yang2cabf812012-08-28 02:39:04 +0800763
764
Tom Wai-Hong Tam700c9fd2012-11-15 18:18:30 +0800765 def setup_ec_write_protect(self, ec_wp):
766 """Setup for EC write-protection.
767
768 It makes sure the EC in the requested write-protection state. If not, it
769 flips the state. Flipping the write-protection requires DUT reboot.
770
771 Args:
772 ec_wp: True to request EC write-protected; False to request EC not
773 write-protected; None to do nothing.
774 """
775 if ec_wp is None:
776 self._old_ec_wp = None
777 return
778 self._old_ec_wp = self.checkers.crossystem_checker({'wpsw_boot': '1'})
779 if ec_wp != self._old_ec_wp:
780 logging.info('The test required EC is %swrite-protected. Reboot '
781 'and flip the state.', '' if ec_wp else 'not ')
782 self.run_faft_step({
Tom Wai-Hong Tam44204b32012-11-20 13:55:40 +0800783 'reboot_action': (self.set_ec_write_protect_and_reboot, ec_wp)
Tom Wai-Hong Tam700c9fd2012-11-15 18:18:30 +0800784 })
785
786
787 def restore_ec_write_protect(self):
788 """Restore the original EC write-protection."""
789 if self._old_ec_wp is None:
790 return
791 if not self.checkers.crossystem_checker(
792 {'wpsw_boot': '1' if self._old_ec_wp else '0'}):
793 logging.info('Restore the original EC write protection and reboot.')
794 self.run_faft_step({
Tom Wai-Hong Tam44204b32012-11-20 13:55:40 +0800795 'reboot_action': (self.set_ec_write_protect_and_reboot,
Tom Wai-Hong Tam700c9fd2012-11-15 18:18:30 +0800796 self._old_ec_wp)
797 })
798
799
Tom Wai-Hong Tam91612bc2012-10-29 16:04:21 +0800800 def press_ctrl_d(self):
Tom Wai-Hong Tam1db43832011-12-09 10:50:56 +0800801 """Send Ctrl-D key to DUT."""
Tom Wai-Hong Tam9c15b4b2012-10-29 17:59:26 +0800802 if not self.client_attr.has_keyboard:
803 logging.info('Running usbkm232-ctrld...')
804 os.system('usbkm232-ctrld')
Tom Wai-Hong Tam1db43832011-12-09 10:50:56 +0800805 else:
806 self.servo.ctrl_d()
807
808
Tom Wai-Hong Tam91612bc2012-10-29 16:04:21 +0800809 def press_ctrl_u(self):
Tom Wai-Hong Tamadbec3e2012-10-15 14:20:15 +0800810 """Send Ctrl-U key to DUT.
811
812 Raises:
813 error.TestError: if a non-Chrome EC device or no Ctrl-U command given
814 on a no-build-in-keyboard device.
815 """
Tom Wai-Hong Tam9c15b4b2012-10-29 17:59:26 +0800816 if not self.client_attr.has_keyboard:
817 logging.info('Running usbkm232-ctrlu...')
818 os.system('usbkm232-ctrlu')
Tom Wai-Hong Tamadbec3e2012-10-15 14:20:15 +0800819 elif self.check_ec_capability(['keyboard'], suppress_warning=True):
820 self.ec.key_down('<ctrl_l>')
821 self.ec.key_down('u')
822 self.ec.key_up('u')
823 self.ec.key_up('<ctrl_l>')
824 elif self.client_attr.has_keyboard:
825 raise error.TestError(
826 "Can't send Ctrl-U to DUT without using Chrome EC.")
827 else:
828 raise error.TestError(
829 "Should specify the ctrl_u_cmd argument.")
830
831
Tom Wai-Hong Tam91612bc2012-10-29 16:04:21 +0800832 def press_enter(self):
Tom Wai-Hong Tam1db43832011-12-09 10:50:56 +0800833 """Send Enter key to DUT."""
Tom Wai-Hong Tam9c15b4b2012-10-29 17:59:26 +0800834 if not self.client_attr.has_keyboard:
835 logging.info('Running usbkm232-enter...')
836 os.system('usbkm232-enter')
Tom Wai-Hong Tam1db43832011-12-09 10:50:56 +0800837 else:
838 self.servo.enter_key()
839
840
Tom Wai-Hong Tam56977782012-11-23 16:13:28 +0800841 def wait_dev_screen_and_ctrl_d(self):
842 """Wait for firmware warning screen and press Ctrl-D."""
843 time.sleep(self.delay.dev_screen)
844 self.press_ctrl_d()
845
846
Tom Wai-Hong Tama9c1a502011-11-10 06:39:26 +0800847 def wait_fw_screen_and_ctrl_d(self):
848 """Wait for firmware warning screen and press Ctrl-D."""
Tom Wai-Hong Tam41738762012-10-29 14:32:39 +0800849 time.sleep(self.delay.firmware_screen)
Tom Wai-Hong Tam91612bc2012-10-29 16:04:21 +0800850 self.press_ctrl_d()
Tom Wai-Hong Tama9c1a502011-11-10 06:39:26 +0800851
852
Tom Wai-Hong Tamadbec3e2012-10-15 14:20:15 +0800853 def wait_fw_screen_and_ctrl_u(self):
854 """Wait for firmware warning screen and press Ctrl-U."""
Tom Wai-Hong Tam41738762012-10-29 14:32:39 +0800855 time.sleep(self.delay.firmware_screen)
Tom Wai-Hong Tam91612bc2012-10-29 16:04:21 +0800856 self.press_ctrl_u()
Tom Wai-Hong Tamadbec3e2012-10-15 14:20:15 +0800857
858
Tom Wai-Hong Tam78709592011-12-19 11:16:50 +0800859 def wait_fw_screen_and_trigger_recovery(self, need_dev_transition=False):
860 """Wait for firmware warning screen and trigger recovery boot."""
Tom Wai-Hong Tam41738762012-10-29 14:32:39 +0800861 time.sleep(self.delay.firmware_screen)
Tom Wai-Hong Tam91612bc2012-10-29 16:04:21 +0800862 self.press_enter()
Tom Wai-Hong Tam78709592011-12-19 11:16:50 +0800863
864 # For Alex/ZGB, there is a dev warning screen in text mode.
865 # Skip it by pressing Ctrl-D.
866 if need_dev_transition:
Tom Wai-Hong Tam41738762012-10-29 14:32:39 +0800867 time.sleep(self.delay.legacy_text_screen)
Tom Wai-Hong Tam91612bc2012-10-29 16:04:21 +0800868 self.press_ctrl_d()
Tom Wai-Hong Tam78709592011-12-19 11:16:50 +0800869
870
Mike Truty49153d82012-08-21 22:27:30 -0500871 def wait_fw_screen_and_unplug_usb(self):
872 """Wait for firmware warning screen and then unplug the servo USB."""
Tom Wai-Hong Tam41738762012-10-29 14:32:39 +0800873 time.sleep(self.delay.load_usb)
Tom Wai-Hong Tam5d2f4702011-12-06 10:42:31 +0800874 self.servo.set('usb_mux_sel1', 'servo_sees_usbkey')
Tom Wai-Hong Tam41738762012-10-29 14:32:39 +0800875 time.sleep(self.delay.between_usb_plug)
Mike Truty49153d82012-08-21 22:27:30 -0500876
877
878 def wait_fw_screen_and_plug_usb(self):
879 """Wait for firmware warning screen and then unplug and plug the USB."""
880 self.wait_fw_screen_and_unplug_usb()
Tom Wai-Hong Tam5d2f4702011-12-06 10:42:31 +0800881 self.servo.set('usb_mux_sel1', 'dut_sees_usbkey')
882
883
Tom Wai-Hong Tam78709592011-12-19 11:16:50 +0800884 def wait_fw_screen_and_press_power(self):
885 """Wait for firmware warning screen and press power button."""
Tom Wai-Hong Tam41738762012-10-29 14:32:39 +0800886 time.sleep(self.delay.firmware_screen)
Tom Wai-Hong Tam7317c042012-08-14 11:59:06 +0800887 # While the firmware screen, the power button probing loop sleeps
888 # 0.25 second on every scan. Use the normal delay (1.2 second) for
889 # power press.
890 self.servo.power_normal_press()
Tom Wai-Hong Tam78709592011-12-19 11:16:50 +0800891
892
Tom Wai-Hong Tam4f5e5922012-07-27 16:23:15 +0800893 def wait_longer_fw_screen_and_press_power(self):
894 """Wait for firmware screen without timeout and press power button."""
Tom Wai-Hong Tam41738762012-10-29 14:32:39 +0800895 time.sleep(self.delay.dev_screen_timeout)
Tom Wai-Hong Tam4f5e5922012-07-27 16:23:15 +0800896 self.wait_fw_screen_and_press_power()
897
898
Tom Wai-Hong Tam78709592011-12-19 11:16:50 +0800899 def wait_fw_screen_and_close_lid(self):
900 """Wait for firmware warning screen and close lid."""
Tom Wai-Hong Tam41738762012-10-29 14:32:39 +0800901 time.sleep(self.delay.firmware_screen)
Tom Wai-Hong Tam78709592011-12-19 11:16:50 +0800902 self.servo.lid_close()
903
904
Tom Wai-Hong Tam473cfa72012-07-27 17:16:57 +0800905 def wait_longer_fw_screen_and_close_lid(self):
906 """Wait for firmware screen without timeout and close lid."""
Tom Wai-Hong Tam41738762012-10-29 14:32:39 +0800907 time.sleep(self.delay.firmware_screen)
Tom Wai-Hong Tam473cfa72012-07-27 17:16:57 +0800908 self.wait_fw_screen_and_close_lid()
909
910
Tom Wai-Hong Tam01d5e572012-10-23 10:07:11 +0800911 def setup_gbb_flags(self):
912 """Setup the GBB flags for FAFT test."""
913 if self.check_setup_done('gbb_flags'):
914 return
915
916 logging.info('Set proper GBB flags for test.')
917 self.clear_set_gbb_flags(vboot.GBB_FLAG_DEV_SCREEN_SHORT_DELAY |
918 vboot.GBB_FLAG_FORCE_DEV_SWITCH_ON |
919 vboot.GBB_FLAG_FORCE_DEV_BOOT_USB |
920 vboot.GBB_FLAG_DISABLE_FW_ROLLBACK_CHECK,
Gediminas Ramanauskasba352ad2012-11-09 09:43:32 -0800921 vboot.GBB_FLAG_ENTER_TRIGGERS_TONORM |
922 vboot.GBB_FLAG_FAFT_KEY_OVERIDE)
Tom Wai-Hong Tam01d5e572012-10-23 10:07:11 +0800923 self.mark_setup_done('gbb_flags')
924
925
Tom Wai-Hong Tamfd590c92011-11-25 11:50:57 +0800926 def setup_tried_fwb(self, tried_fwb):
927 """Setup for fw B tried state.
928
929 It makes sure the system in the requested fw B tried state. If not, it
930 tries to do so.
931
932 Args:
933 tried_fwb: True if requested in tried_fwb=1; False if tried_fwb=0.
934 """
935 if tried_fwb:
Vic Yangf93f7022012-10-31 09:40:36 +0800936 if not self.checkers.crossystem_checker({'tried_fwb': '1'}):
Tom Wai-Hong Tamfd590c92011-11-25 11:50:57 +0800937 logging.info(
938 'Firmware is not booted with tried_fwb. Reboot into it.')
939 self.run_faft_step({
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800940 'userspace_action': self.faft_client.system.set_try_fw_b,
Tom Wai-Hong Tamfd590c92011-11-25 11:50:57 +0800941 })
942 else:
Vic Yangf93f7022012-10-31 09:40:36 +0800943 if not self.checkers.crossystem_checker({'tried_fwb': '0'}):
Tom Wai-Hong Tamfd590c92011-11-25 11:50:57 +0800944 logging.info(
945 'Firmware is booted with tried_fwb. Reboot to clear.')
946 self.run_faft_step({})
947
948
Tom Wai-Hong Tama373f802012-07-31 21:16:48 +0800949 def enable_rec_mode_and_reboot(self):
950 """Switch to rec mode and reboot.
951
952 This method emulates the behavior of the old physical recovery switch,
953 i.e. switch ON + reboot + switch OFF, and the new keyboard controlled
954 recovery mode, i.e. just press Power + Esc + Refresh.
955 """
Tom Wai-Hong Tam80419a82012-10-30 09:10:00 +0800956 if self.client_attr.chrome_ec:
Tom Wai-Hong Tam41128082012-11-16 12:02:45 +0800957 # Reset twice to emulate a long recovery-key-combo hold.
958 cold_reset_num = 2 if self.client_attr.long_rec_combo else 1
Tom Wai-Hong Tam4c9684a2012-12-11 10:48:05 +0800959 for i in range(cold_reset_num):
960 if i:
961 time.sleep(self.delay.ec_boot_to_console)
Tom Wai-Hong Tam41128082012-11-16 12:02:45 +0800962 # Cold reset to clear EC_IN_RW signal
963 self.servo.set('cold_reset', 'on')
964 time.sleep(self.delay.hold_cold_reset)
965 self.servo.set('cold_reset', 'off')
Tom Wai-Hong Tambb92e6c2012-10-30 11:06:09 +0800966 self.ec.reboot("ap-off")
Tom Wai-Hong Tam41738762012-10-29 14:32:39 +0800967 time.sleep(self.delay.ec_boot_to_console)
Tom Wai-Hong Tam665281c2012-10-30 11:55:10 +0800968 self.ec.set_hostevent(chrome_ec.HOSTEVENT_KEYBOARD_RECOVERY)
Vic Yang611dd852012-08-02 15:36:31 +0800969 self.servo.power_short_press()
Gediminas Ramanauskasba352ad2012-11-09 09:43:32 -0800970 elif self.client_attr.broken_rec_mode:
Tom Wai-Hong Tamc5c14ef2012-11-20 16:33:37 +0800971 if self._host and self._host.has_power():
Gediminas Ramanauskasba352ad2012-11-09 09:43:32 -0800972 self._host.power_cycle()
973 else:
974 logging.info('You have %d seconds to power cycle this device.',
975 self.delay.user_power_cycle)
976 time.sleep(self.delay.user_power_cycle)
977 logging.info('Booting to recovery mode.')
978 self.servo.custom_recovery_mode()
Tom Wai-Hong Tamac943172012-08-01 10:38:39 +0800979 else:
980 self.servo.enable_recovery_mode()
981 self.cold_reboot()
Tom Wai-Hong Tamad4aaae2012-12-12 11:02:06 +0800982 time.sleep(self.delay.ec_boot_to_console)
Tom Wai-Hong Tamac943172012-08-01 10:38:39 +0800983 self.servo.disable_recovery_mode()
Tom Wai-Hong Tama373f802012-07-31 21:16:48 +0800984
985
Tom Wai-Hong Tam0b9e6d72012-07-31 20:54:06 +0800986 def enable_dev_mode_and_reboot(self):
987 """Switch to developer mode and reboot."""
Vic Yange7553162012-06-20 16:20:47 +0800988 if self.client_attr.keyboard_dev:
989 self.enable_keyboard_dev_mode()
990 else:
991 self.servo.enable_development_mode()
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800992 self.faft_client.system.run_shell_command(
Vic Yange7553162012-06-20 16:20:47 +0800993 'chromeos-firmwareupdate --mode todev && reboot')
Tom Wai-Hong Tam78709592011-12-19 11:16:50 +0800994
995
Tom Wai-Hong Tam0b9e6d72012-07-31 20:54:06 +0800996 def enable_normal_mode_and_reboot(self):
997 """Switch to normal mode and reboot."""
Vic Yange7553162012-06-20 16:20:47 +0800998 if self.client_attr.keyboard_dev:
999 self.disable_keyboard_dev_mode()
1000 else:
1001 self.servo.disable_development_mode()
Chun-ting Changd43aa9b2012-11-16 10:12:05 +08001002 self.faft_client.system.run_shell_command(
Vic Yange7553162012-06-20 16:20:47 +08001003 'chromeos-firmwareupdate --mode tonormal && reboot')
1004
1005
1006 def wait_fw_screen_and_switch_keyboard_dev_mode(self, dev):
1007 """Wait for firmware screen and then switch into or out of dev mode.
1008
1009 Args:
1010 dev: True if switching into dev mode. Otherwise, False.
1011 """
Tom Wai-Hong Tam41738762012-10-29 14:32:39 +08001012 time.sleep(self.delay.firmware_screen)
Vic Yange7553162012-06-20 16:20:47 +08001013 if dev:
Tom Wai-Hong Tam91612bc2012-10-29 16:04:21 +08001014 self.press_ctrl_d()
Vic Yange7553162012-06-20 16:20:47 +08001015 else:
Tom Wai-Hong Tam91612bc2012-10-29 16:04:21 +08001016 self.press_enter()
Vic Yang0dc84b82012-10-31 12:29:39 +08001017 time.sleep(self.delay.confirm_screen)
Tom Wai-Hong Tam91612bc2012-10-29 16:04:21 +08001018 self.press_enter()
Vic Yange7553162012-06-20 16:20:47 +08001019
1020
1021 def enable_keyboard_dev_mode(self):
1022 logging.info("Enabling keyboard controlled developer mode")
Tom Wai-Hong Tamf1a17d72012-07-26 11:39:52 +08001023 # Plug out USB disk for preventing recovery boot without warning
1024 self.servo.set('usb_mux_sel1', 'servo_sees_usbkey')
Vic Yange7553162012-06-20 16:20:47 +08001025 # Rebooting EC with rec mode on. Should power on AP.
Tom Wai-Hong Tama373f802012-07-31 21:16:48 +08001026 self.enable_rec_mode_and_reboot()
Tom Wai-Hong Tam8c54eb82012-08-01 10:31:07 +08001027 self.wait_for_client_offline()
Vic Yange7553162012-06-20 16:20:47 +08001028 self.wait_fw_screen_and_switch_keyboard_dev_mode(dev=True)
Vic Yange7553162012-06-20 16:20:47 +08001029
1030
1031 def disable_keyboard_dev_mode(self):
1032 logging.info("Disabling keyboard controlled developer mode")
Gediminas Ramanauskasba352ad2012-11-09 09:43:32 -08001033 if (not self.client_attr.chrome_ec and
1034 not self.client_attr.broken_rec_mode):
Vic Yang611dd852012-08-02 15:36:31 +08001035 self.servo.disable_recovery_mode()
Tom Wai-Hong Tam7ad99ab2012-07-30 19:30:51 +08001036 self.cold_reboot()
Tom Wai-Hong Tam8c54eb82012-08-01 10:31:07 +08001037 self.wait_for_client_offline()
Vic Yange7553162012-06-20 16:20:47 +08001038 self.wait_fw_screen_and_switch_keyboard_dev_mode(dev=False)
Tom Wai-Hong Tam78709592011-12-19 11:16:50 +08001039
1040
Tom Wai-Hong Tama9c1a502011-11-10 06:39:26 +08001041 def setup_dev_mode(self, dev_mode):
1042 """Setup for development mode.
1043
Tom Wai-Hong Tamfd590c92011-11-25 11:50:57 +08001044 It makes sure the system in the requested normal/dev mode. If not, it
Tom Wai-Hong Tama9c1a502011-11-10 06:39:26 +08001045 tries to do so.
1046
1047 Args:
1048 dev_mode: True if requested in dev mode; False if normal mode.
1049 """
Tom Wai-Hong Tamfd590c92011-11-25 11:50:57 +08001050 # Change the default firmware_action for dev mode passing the fw screen.
1051 self.register_faft_template({
Tom Wai-Hong Tam56977782012-11-23 16:13:28 +08001052 'firmware_action': (self.wait_dev_screen_and_ctrl_d if dev_mode
Tom Wai-Hong Tamfd590c92011-11-25 11:50:57 +08001053 else None),
1054 })
Tom Wai-Hong Tama9c1a502011-11-10 06:39:26 +08001055 if dev_mode:
Vic Yange7553162012-06-20 16:20:47 +08001056 if (not self.client_attr.keyboard_dev and
Vic Yangf93f7022012-10-31 09:40:36 +08001057 not self.checkers.crossystem_checker({'devsw_cur': '1'})):
Tom Wai-Hong Tama9c1a502011-11-10 06:39:26 +08001058 logging.info('Dev switch is not on. Now switch it on.')
1059 self.servo.enable_development_mode()
Vic Yangf93f7022012-10-31 09:40:36 +08001060 if not self.checkers.crossystem_checker({'devsw_boot': '1',
Tom Wai-Hong Tama9c1a502011-11-10 06:39:26 +08001061 'mainfw_type': 'developer'}):
1062 logging.info('System is not in dev mode. Reboot into it.')
Tom Wai-Hong Tamfd590c92011-11-25 11:50:57 +08001063 self.run_faft_step({
Vic Yange7553162012-06-20 16:20:47 +08001064 'userspace_action': None if self.client_attr.keyboard_dev
Chun-ting Changd43aa9b2012-11-16 10:12:05 +08001065 else (self.faft_client.system.run_shell_command,
Tom Wai-Hong Tamc7ecfca2011-12-06 11:12:31 +08001066 'chromeos-firmwareupdate --mode todev && reboot'),
Vic Yange7553162012-06-20 16:20:47 +08001067 'reboot_action': self.enable_keyboard_dev_mode if
1068 self.client_attr.keyboard_dev else None,
Tom Wai-Hong Tamfd590c92011-11-25 11:50:57 +08001069 })
Tom Wai-Hong Tama9c1a502011-11-10 06:39:26 +08001070 else:
Vic Yange7553162012-06-20 16:20:47 +08001071 if (not self.client_attr.keyboard_dev and
Vic Yangf93f7022012-10-31 09:40:36 +08001072 not self.checkers.crossystem_checker({'devsw_cur': '0'})):
Tom Wai-Hong Tama9c1a502011-11-10 06:39:26 +08001073 logging.info('Dev switch is not off. Now switch it off.')
1074 self.servo.disable_development_mode()
Vic Yangf93f7022012-10-31 09:40:36 +08001075 if not self.checkers.crossystem_checker({'devsw_boot': '0',
Tom Wai-Hong Tama9c1a502011-11-10 06:39:26 +08001076 'mainfw_type': 'normal'}):
1077 logging.info('System is not in normal mode. Reboot into it.')
Tom Wai-Hong Tamfd590c92011-11-25 11:50:57 +08001078 self.run_faft_step({
Vic Yange7553162012-06-20 16:20:47 +08001079 'userspace_action': None if self.client_attr.keyboard_dev
Chun-ting Changd43aa9b2012-11-16 10:12:05 +08001080 else (self.faft_client.system.run_shell_command,
Tom Wai-Hong Tamc7ecfca2011-12-06 11:12:31 +08001081 'chromeos-firmwareupdate --mode tonormal && reboot'),
Vic Yange7553162012-06-20 16:20:47 +08001082 'reboot_action': self.disable_keyboard_dev_mode if
1083 self.client_attr.keyboard_dev else None,
Tom Wai-Hong Tamfd590c92011-11-25 11:50:57 +08001084 })
Tom Wai-Hong Tama9c1a502011-11-10 06:39:26 +08001085
1086
Tom Wai-Hong Tamcfda61f2011-11-02 17:41:01 +08001087 def setup_kernel(self, part):
1088 """Setup for kernel test.
1089
1090 It makes sure both kernel A and B bootable and the current boot is
1091 the requested kernel part.
1092
1093 Args:
Tom Wai-Hong Tama9c1a502011-11-10 06:39:26 +08001094 part: A string of kernel partition number or 'a'/'b'.
Tom Wai-Hong Tamcfda61f2011-11-02 17:41:01 +08001095 """
1096 self.ensure_kernel_boot(part)
Chun-ting Changd43aa9b2012-11-16 10:12:05 +08001097 if self.faft_client.kernel.diff_a_b():
Tom Wai-Hong Tam622d0ba2012-08-15 16:29:05 +08001098 self.copy_kernel_and_rootfs(from_part=part,
1099 to_part=self.OTHER_KERNEL_MAP[part])
Tom Wai-Hong Tamcfda61f2011-11-02 17:41:01 +08001100 self.reset_and_prioritize_kernel(part)
1101
1102
1103 def reset_and_prioritize_kernel(self, part):
1104 """Make the requested partition highest priority.
1105
1106 This function also reset kerenl A and B to bootable.
1107
1108 Args:
Tom Wai-Hong Tama9c1a502011-11-10 06:39:26 +08001109 part: A string of partition number to be prioritized.
Tom Wai-Hong Tamcfda61f2011-11-02 17:41:01 +08001110 """
Chun-ting Changd43aa9b2012-11-16 10:12:05 +08001111 root_dev = self.faft_client.system.get_root_dev()
Tom Wai-Hong Tamcfda61f2011-11-02 17:41:01 +08001112 # Reset kernel A and B to bootable.
Chun-ting Changd43aa9b2012-11-16 10:12:05 +08001113 self.faft_client.system.run_shell_command(
1114 'cgpt add -i%s -P1 -S1 -T0 %s' % (self.KERNEL_MAP['a'], root_dev))
1115 self.faft_client.system.run_shell_command(
1116 'cgpt add -i%s -P1 -S1 -T0 %s' % (self.KERNEL_MAP['b'], root_dev))
Tom Wai-Hong Tamcfda61f2011-11-02 17:41:01 +08001117 # Set kernel part highest priority.
Chun-ting Changd43aa9b2012-11-16 10:12:05 +08001118 self.faft_client.system.run_shell_command('cgpt prioritize -i%s %s' %
Tom Wai-Hong Tamcfda61f2011-11-02 17:41:01 +08001119 (self.KERNEL_MAP[part], root_dev))
Tom Wai-Hong Tam6a863ba2011-12-08 10:13:28 +08001120 # Safer to sync and wait until the cgpt status written to the disk.
Chun-ting Changd43aa9b2012-11-16 10:12:05 +08001121 self.faft_client.system.run_shell_command('sync')
Tom Wai-Hong Tam41738762012-10-29 14:32:39 +08001122 time.sleep(self.delay.sync)
Tom Wai-Hong Tamcfda61f2011-11-02 17:41:01 +08001123
1124
Tom Wai-Hong Tam7ad99ab2012-07-30 19:30:51 +08001125 def warm_reboot(self):
1126 """Request a warm reboot.
1127
Tom Wai-Hong Tamb06f0802012-07-31 16:27:50 +08001128 A wrapper for underlying servo warm reset.
Tom Wai-Hong Tam7ad99ab2012-07-30 19:30:51 +08001129 """
Tom Wai-Hong Tamb06f0802012-07-31 16:27:50 +08001130 # Use cold reset if the warm reset is broken.
1131 if self.client_attr.broken_warm_reset:
Gediminas Ramanauskase021e152012-09-04 19:10:59 -07001132 logging.info('broken_warm_reset is True. Cold rebooting instead.')
1133 self.cold_reboot()
Tom Wai-Hong Tamb06f0802012-07-31 16:27:50 +08001134 else:
1135 self.servo.warm_reset()
Tom Wai-Hong Tam7ad99ab2012-07-30 19:30:51 +08001136
1137
1138 def cold_reboot(self):
1139 """Request a cold reboot.
1140
1141 A wrapper for underlying servo cold reset.
1142 """
Gediminas Ramanauskasc6025692012-10-23 14:33:40 -07001143 if self.client_attr.broken_warm_reset:
Tom Wai-Hong Tama276d0a2012-08-22 11:15:17 +08001144 self.servo.set('pwr_button', 'press')
1145 self.servo.set('cold_reset', 'on')
1146 self.servo.set('cold_reset', 'off')
Tom Wai-Hong Tam41738762012-10-29 14:32:39 +08001147 time.sleep(self.delay.ec_boot_to_pwr_button)
Tom Wai-Hong Tama276d0a2012-08-22 11:15:17 +08001148 self.servo.set('pwr_button', 'release')
Tom Wai-Hong Tam7ad99ab2012-07-30 19:30:51 +08001149 else:
1150 self.servo.cold_reset()
1151
1152
Tom Wai-Hong Tamb21b6b42012-07-26 10:46:30 +08001153 def sync_and_warm_reboot(self):
Tom Wai-Hong Tamf1e34972011-11-02 17:07:04 +08001154 """Request the client sync and do a warm reboot.
1155
1156 This is the default reboot action on FAFT.
1157 """
Chun-ting Changd43aa9b2012-11-16 10:12:05 +08001158 self.faft_client.system.run_shell_command('sync')
Tom Wai-Hong Tam41738762012-10-29 14:32:39 +08001159 time.sleep(self.delay.sync)
Tom Wai-Hong Tam7ad99ab2012-07-30 19:30:51 +08001160 self.warm_reboot()
Tom Wai-Hong Tamf1e34972011-11-02 17:07:04 +08001161
1162
Tom Wai-Hong Tamb21b6b42012-07-26 10:46:30 +08001163 def sync_and_cold_reboot(self):
1164 """Request the client sync and do a cold reboot.
1165
1166 This reboot action is used to reset EC for recovery mode.
1167 """
Chun-ting Changd43aa9b2012-11-16 10:12:05 +08001168 self.faft_client.system.run_shell_command('sync')
Tom Wai-Hong Tam41738762012-10-29 14:32:39 +08001169 time.sleep(self.delay.sync)
Tom Wai-Hong Tam7ad99ab2012-07-30 19:30:51 +08001170 self.cold_reboot()
Tom Wai-Hong Tamb21b6b42012-07-26 10:46:30 +08001171
1172
Tom Wai-Hong Tambb92e6c2012-10-30 11:06:09 +08001173 def sync_and_ec_reboot(self, flags=''):
Vic Yangaeb10392012-08-28 09:25:09 +08001174 """Request the client sync and do a EC triggered reboot.
1175
1176 Args:
Tom Wai-Hong Tambb92e6c2012-10-30 11:06:09 +08001177 flags: Optional, a space-separated string of flags passed to EC
1178 reboot command, including:
1179 default: EC soft reboot;
1180 'hard': EC cold/hard reboot.
Vic Yangaeb10392012-08-28 09:25:09 +08001181 """
Chun-ting Changd43aa9b2012-11-16 10:12:05 +08001182 self.faft_client.system.run_shell_command('sync')
Tom Wai-Hong Tam41738762012-10-29 14:32:39 +08001183 time.sleep(self.delay.sync)
Tom Wai-Hong Tambb92e6c2012-10-30 11:06:09 +08001184 self.ec.reboot(flags)
Tom Wai-Hong Tamad4aaae2012-12-12 11:02:06 +08001185 time.sleep(self.delay.ec_boot_to_console)
Vic Yangf86728a2012-07-30 10:44:07 +08001186 self.check_lid_and_power_on()
1187
1188
Tom Wai-Hong Tam3d00ab72012-11-14 10:39:22 +08001189 def reboot_with_factory_install_shim(self):
1190 """Request reboot with factory install shim to reset TPM.
Chun-ting Changa4f65532012-10-17 16:57:28 +08001191
Tom Wai-Hong Tam3d00ab72012-11-14 10:39:22 +08001192 Factory install shim requires dev mode enabled. So this method switches
1193 firmware to dev mode first and reboot. The client uses factory install
1194 shim to reset TPM values.
Chun-ting Changa4f65532012-10-17 16:57:28 +08001195 """
Tom Wai-Hong Tam3d00ab72012-11-14 10:39:22 +08001196 # Unplug USB first to avoid the complicated USB autoboot cases.
1197 self.servo.set('usb_mux_sel1', 'servo_sees_usbkey')
Vic Yangf93f7022012-10-31 09:40:36 +08001198 is_dev = self.checkers.crossystem_checker({'devsw_boot': '1'})
Chun-ting Changa4f65532012-10-17 16:57:28 +08001199 if not is_dev:
1200 self.enable_dev_mode_and_reboot()
Vic Yangf1fdf712012-10-31 12:09:22 +08001201 time.sleep(self.delay.sync)
Chun-ting Changa4f65532012-10-17 16:57:28 +08001202 self.enable_rec_mode_and_reboot()
Tom Wai-Hong Tam3d00ab72012-11-14 10:39:22 +08001203 self.wait_fw_screen_and_plug_usb()
Tom Wai-Hong Tam41738762012-10-29 14:32:39 +08001204 time.sleep(self.delay.install_shim_done)
Chun-ting Changa4f65532012-10-17 16:57:28 +08001205 self.warm_reboot()
1206
1207
Tom Wai-Hong Tamc8f2ca02012-09-14 11:18:01 +08001208 def full_power_off_and_on(self):
1209 """Shutdown the device by pressing power button and power on again."""
1210 # Press power button to trigger Chrome OS normal shutdown process.
Tom Wai-Hong Tambe464992012-12-12 10:54:07 +08001211 # We use a customized delay since the normal-press 1.2s is not enough.
1212 self.servo.power_key(self.delay.hold_pwr_button)
Tom Wai-Hong Tam41738762012-10-29 14:32:39 +08001213 time.sleep(self.delay.shutdown)
Tom Wai-Hong Tamc8f2ca02012-09-14 11:18:01 +08001214 # Short press power button to boot DUT again.
1215 self.servo.power_short_press()
1216
1217
Vic Yangf86728a2012-07-30 10:44:07 +08001218 def check_lid_and_power_on(self):
1219 """
1220 On devices with EC software sync, system powers on after EC reboots if
1221 lid is open. Otherwise, the EC shuts down CPU after about 3 seconds.
1222 This method checks lid switch state and presses power button if
1223 necessary.
1224 """
1225 if self.servo.get("lid_open") == "no":
Tom Wai-Hong Tam41738762012-10-29 14:32:39 +08001226 time.sleep(self.delay.software_sync)
Vic Yangf86728a2012-07-30 10:44:07 +08001227 self.servo.power_short_press()
Vic Yang59cac9c2012-05-21 15:28:42 +08001228
1229
Tom Wai-Hong Tam78709592011-12-19 11:16:50 +08001230 def _modify_usb_kernel(self, usb_dev, from_magic, to_magic):
1231 """Modify the kernel header magic in USB stick.
1232
1233 The kernel header magic is the first 8-byte of kernel partition.
1234 We modify it to make it fail on kernel verification check.
1235
1236 Args:
1237 usb_dev: A string of USB stick path on the host, like '/dev/sdc'.
1238 from_magic: A string of magic which we change it from.
1239 to_magic: A string of magic which we change it to.
1240
1241 Raises:
1242 error.TestError: if failed to change magic.
1243 """
1244 assert len(from_magic) == 8
1245 assert len(to_magic) == 8
Tom Wai-Hong Tama1d9a0f2011-12-23 09:13:33 +08001246 # USB image only contains one kernel.
1247 kernel_part = self._join_part(usb_dev, self.KERNEL_MAP['a'])
Tom Wai-Hong Tam78709592011-12-19 11:16:50 +08001248 read_cmd = "sudo dd if=%s bs=8 count=1 2>/dev/null" % kernel_part
1249 current_magic = utils.system_output(read_cmd)
1250 if current_magic == to_magic:
Vic Yang772df8a2012-10-31 10:10:49 +08001251 logging.info("The kernel magic is already %s.", current_magic)
Tom Wai-Hong Tam78709592011-12-19 11:16:50 +08001252 return
1253 if current_magic != from_magic:
1254 raise error.TestError("Invalid kernel image on USB: wrong magic.")
1255
Vic Yang772df8a2012-10-31 10:10:49 +08001256 logging.info('Modify the kernel magic in USB, from %s to %s.',
1257 from_magic, to_magic)
Tom Wai-Hong Tam78709592011-12-19 11:16:50 +08001258 write_cmd = ("echo -n '%s' | sudo dd of=%s oflag=sync conv=notrunc "
1259 " 2>/dev/null" % (to_magic, kernel_part))
1260 utils.system(write_cmd)
1261
1262 if utils.system_output(read_cmd) != to_magic:
1263 raise error.TestError("Failed to write new magic.")
1264
1265
1266 def corrupt_usb_kernel(self, usb_dev):
1267 """Corrupt USB kernel by modifying its magic from CHROMEOS to CORRUPTD.
1268
1269 Args:
1270 usb_dev: A string of USB stick path on the host, like '/dev/sdc'.
1271 """
1272 self._modify_usb_kernel(usb_dev, self.CHROMEOS_MAGIC,
1273 self.CORRUPTED_MAGIC)
1274
1275
1276 def restore_usb_kernel(self, usb_dev):
1277 """Restore USB kernel by modifying its magic from CORRUPTD to CHROMEOS.
1278
1279 Args:
1280 usb_dev: A string of USB stick path on the host, like '/dev/sdc'.
1281 """
1282 self._modify_usb_kernel(usb_dev, self.CORRUPTED_MAGIC,
1283 self.CHROMEOS_MAGIC)
1284
1285
Tom Wai-Hong Tamfc700b52012-09-13 21:33:52 +08001286 def _call_action(self, action_tuple, check_status=False):
Tom Wai-Hong Tama70f0fe2011-09-02 18:28:47 +08001287 """Call the action function with/without arguments.
1288
1289 Args:
Tom Wai-Hong Tamfc700b52012-09-13 21:33:52 +08001290 action_tuple: A function, or a tuple (function, args, error_msg),
1291 in which, args and error_msg are optional. args is
1292 either a value or a tuple if multiple arguments.
Vic Yang52116d42012-11-05 16:22:34 +08001293 This can also be a list containing multiple function
1294 or tuple. In this case, these actions are called in
1295 sequence.
Tom Wai-Hong Tamfc700b52012-09-13 21:33:52 +08001296 check_status: Check the return value of action function. If not
1297 succeed, raises a TestFail exception.
Tom Wai-Hong Tama70f0fe2011-09-02 18:28:47 +08001298
1299 Returns:
1300 The result value of the action function.
Tom Wai-Hong Tamfc700b52012-09-13 21:33:52 +08001301
1302 Raises:
1303 error.TestError: An error when the action function is not callable.
1304 error.TestFail: When check_status=True, action function not succeed.
Tom Wai-Hong Tama70f0fe2011-09-02 18:28:47 +08001305 """
Vic Yang52116d42012-11-05 16:22:34 +08001306 if isinstance(action_tuple, list):
1307 return all([self._call_action(action, check_status=check_status)
1308 for action in action_tuple])
1309
Tom Wai-Hong Tamfc700b52012-09-13 21:33:52 +08001310 action = action_tuple
1311 args = ()
1312 error_msg = 'Not succeed'
Tom Wai-Hong Tama70f0fe2011-09-02 18:28:47 +08001313 if isinstance(action_tuple, tuple):
1314 action = action_tuple[0]
Tom Wai-Hong Tamfc700b52012-09-13 21:33:52 +08001315 if len(action_tuple) >= 2:
1316 args = action_tuple[1]
1317 if not isinstance(args, tuple):
1318 args = (args,)
1319 if len(action_tuple) >= 3:
Tom Wai-Hong Tamff560882012-10-15 16:50:06 +08001320 error_msg = action_tuple[2]
Tom Wai-Hong Tama70f0fe2011-09-02 18:28:47 +08001321
Tom Wai-Hong Tamfc700b52012-09-13 21:33:52 +08001322 if action is None:
1323 return
1324
1325 if not callable(action):
1326 raise error.TestError('action is not callable!')
1327
1328 info_msg = 'calling %s' % str(action)
1329 if args:
1330 info_msg += ' with args %s' % str(args)
1331 logging.info(info_msg)
1332 ret = action(*args)
1333
1334 if check_status and not ret:
1335 raise error.TestFail('%s: %s returning %s' %
1336 (error_msg, info_msg, str(ret)))
1337 return ret
Tom Wai-Hong Tama70f0fe2011-09-02 18:28:47 +08001338
1339
Tom Wai-Hong Tam78709592011-12-19 11:16:50 +08001340 def run_shutdown_process(self, shutdown_action, pre_power_action=None,
Tom Wai-Hong Tam8da40de2012-12-12 12:15:54 +08001341 post_power_action=None, shutdown_timeout=None):
Tom Wai-Hong Tam78709592011-12-19 11:16:50 +08001342 """Run shutdown_action(), which makes DUT shutdown, and power it on.
1343
1344 Args:
1345 shutdown_action: a function which makes DUT shutdown, like pressing
1346 power key.
1347 pre_power_action: a function which is called before next power on.
1348 post_power_action: a function which is called after next power on.
Tom Wai-Hong Tam8da40de2012-12-12 12:15:54 +08001349 shutdown_timeout: a timeout to confirm DUT shutdown.
Tom Wai-Hong Tam78709592011-12-19 11:16:50 +08001350
1351 Raises:
1352 error.TestFail: if the shutdown_action() failed to turn DUT off.
1353 """
1354 self._call_action(shutdown_action)
1355 logging.info('Wait to ensure DUT shut down...')
1356 try:
Tom Wai-Hong Tam8da40de2012-12-12 12:15:54 +08001357 if shutdown_timeout is None:
1358 shutdown_timeout = self.delay.shutdown_timeout
1359 self.wait_for_client(timeout=shutdown_timeout)
Tom Wai-Hong Tam78709592011-12-19 11:16:50 +08001360 raise error.TestFail(
1361 'Should shut the device down after calling %s.' %
1362 str(shutdown_action))
1363 except AssertionError:
1364 logging.info(
1365 'DUT is surely shutdown. We are going to power it on again...')
1366
1367 if pre_power_action:
1368 self._call_action(pre_power_action)
Tom Wai-Hong Tam610262a2012-01-12 14:16:53 +08001369 self.servo.power_short_press()
Tom Wai-Hong Tam78709592011-12-19 11:16:50 +08001370 if post_power_action:
1371 self._call_action(post_power_action)
1372
1373
Tom Wai-Hong Tama70f0fe2011-09-02 18:28:47 +08001374 def register_faft_template(self, template):
1375 """Register FAFT template, the default FAFT_STEP of each step.
1376
Tom Wai-Hong Tam109f63c2011-12-08 14:58:27 +08001377 Any missing field falls back to the original faft_template.
1378
Tom Wai-Hong Tama70f0fe2011-09-02 18:28:47 +08001379 Args:
1380 template: A FAFT_STEP dict.
1381 """
Tom Wai-Hong Tam109f63c2011-12-08 14:58:27 +08001382 self._faft_template.update(template)
Tom Wai-Hong Tama70f0fe2011-09-02 18:28:47 +08001383
1384
1385 def register_faft_sequence(self, sequence):
1386 """Register FAFT sequence.
1387
1388 Args:
1389 sequence: A FAFT_SEQUENCE array which consisted of FAFT_STEP dicts.
1390 """
1391 self._faft_sequence = sequence
1392
1393
Tom Wai-Hong Tamc285f4c2012-10-30 15:44:39 +08001394 def run_faft_step(self, step, no_reboot=False, next_step=None):
Tom Wai-Hong Tam2c50dff2011-11-11 07:01:01 +08001395 """Run a single FAFT step.
1396
1397 Any missing field falls back to faft_template. An empty step means
1398 running the default faft_template.
1399
1400 Args:
1401 step: A FAFT_STEP dict.
1402 no_reboot: True to prevent running reboot_action and firmware_action.
Tom Wai-Hong Tamc285f4c2012-10-30 15:44:39 +08001403 next_step: Optional, a FAFT_STEP dict of the next step, which is used
1404 for diagnostic.
Tom Wai-Hong Tama70f0fe2011-09-02 18:28:47 +08001405
1406 Raises:
Tom Wai-Hong Tamd8445dc2011-12-15 09:00:04 +08001407 error.TestError: An error when the given step is not valid.
Tom Wai-Hong Tam4bb85e22012-10-25 14:35:24 +08001408 error.TestFail: Test failed in waiting DUT reboot.
Tom Wai-Hong Tama70f0fe2011-09-02 18:28:47 +08001409 """
Tom Wai-Hong Tamd8445dc2011-12-15 09:00:04 +08001410 FAFT_STEP_KEYS = ('state_checker', 'userspace_action', 'reboot_action',
1411 'firmware_action', 'install_deps_after_boot')
1412
Tom Wai-Hong Tam2c50dff2011-11-11 07:01:01 +08001413 test = {}
1414 test.update(self._faft_template)
1415 test.update(step)
1416
Tom Wai-Hong Tamd8445dc2011-12-15 09:00:04 +08001417 for key in test:
1418 if key not in FAFT_STEP_KEYS:
Tom Wai-Hong Tam78709592011-12-19 11:16:50 +08001419 raise error.TestError('Invalid key in FAFT step: %s', key)
Tom Wai-Hong Tamd8445dc2011-12-15 09:00:04 +08001420
Tom Wai-Hong Tam2c50dff2011-11-11 07:01:01 +08001421 if test['state_checker']:
Tom Wai-Hong Tamfc700b52012-09-13 21:33:52 +08001422 self._call_action(test['state_checker'], check_status=True)
Tom Wai-Hong Tam2c50dff2011-11-11 07:01:01 +08001423
1424 self._call_action(test['userspace_action'])
1425
1426 # Don't run reboot_action and firmware_action if no_reboot is True.
1427 if not no_reboot:
1428 self._call_action(test['reboot_action'])
1429 self.wait_for_client_offline()
1430 self._call_action(test['firmware_action'])
1431
Vic Yang8eaf5ad2012-09-13 14:05:37 +08001432 try:
1433 if 'install_deps_after_boot' in test:
1434 self.wait_for_client(
1435 install_deps=test['install_deps_after_boot'])
1436 else:
1437 self.wait_for_client()
1438 except AssertionError:
Yusuf Mohsinally928f8c72012-12-11 15:27:02 -08001439 logging.error('wait_for_client() timed out.')
Tom Wai-Hong Tamc285f4c2012-10-30 15:44:39 +08001440 self._restore_routine_from_timeout(next_step)
Tom Wai-Hong Tam2c50dff2011-11-11 07:01:01 +08001441
1442
1443 def run_faft_sequence(self):
1444 """Run FAFT sequence which was previously registered."""
Tom Wai-Hong Tama70f0fe2011-09-02 18:28:47 +08001445 sequence = self._faft_sequence
Tom Wai-Hong Tamc285f4c2012-10-30 15:44:39 +08001446 for index, step in enumerate(sequence):
Vic Yang772df8a2012-10-31 10:10:49 +08001447 logging.info('======== Running FAFT sequence step %d ========',
Tom Wai-Hong Tamc285f4c2012-10-30 15:44:39 +08001448 index + 1)
Tom Wai-Hong Tam2c50dff2011-11-11 07:01:01 +08001449 # Don't reboot in the last step.
Tom Wai-Hong Tamc285f4c2012-10-30 15:44:39 +08001450 if index == len(sequence) - 1:
1451 self.run_faft_step(step, no_reboot=True)
1452 else:
1453 self.run_faft_step(step, next_step=sequence[index + 1])
ctchang38ae4922012-09-03 17:01:16 +08001454
1455
ctchang38ae4922012-09-03 17:01:16 +08001456 def get_current_firmware_sha(self):
1457 """Get current firmware sha of body and vblock.
1458
1459 Returns:
1460 Current firmware sha follows the order (
1461 vblock_a_sha, body_a_sha, vblock_b_sha, body_b_sha)
1462 """
Chun-ting Changd43aa9b2012-11-16 10:12:05 +08001463 current_firmware_sha = (self.faft_client.bios.get_sig_sha('a'),
1464 self.faft_client.bios.get_body_sha('a'),
1465 self.faft_client.bios.get_sig_sha('b'),
1466 self.faft_client.bios.get_body_sha('b'))
ctchang38ae4922012-09-03 17:01:16 +08001467 return current_firmware_sha
1468
1469
Tom Wai-Hong Tame6232342012-09-24 16:18:01 +08001470 def is_firmware_changed(self):
1471 """Check if the current firmware changed, by comparing its SHA.
ctchang38ae4922012-09-03 17:01:16 +08001472
1473 Returns:
Tom Wai-Hong Tame6232342012-09-24 16:18:01 +08001474 True if it is changed, otherwise Flase.
ctchang38ae4922012-09-03 17:01:16 +08001475 """
Tom Wai-Hong Tame6232342012-09-24 16:18:01 +08001476 # Device may not be rebooted after test.
Chun-ting Changd43aa9b2012-11-16 10:12:05 +08001477 self.faft_client.bios.reload()
ctchang38ae4922012-09-03 17:01:16 +08001478
1479 current_sha = self.get_current_firmware_sha()
1480
1481 if current_sha == self._backup_firmware_sha:
Tom Wai-Hong Tame6232342012-09-24 16:18:01 +08001482 return False
ctchang38ae4922012-09-03 17:01:16 +08001483 else:
ctchang38ae4922012-09-03 17:01:16 +08001484 corrupt_VBOOTA = (current_sha[0] != self._backup_firmware_sha[0])
1485 corrupt_FVMAIN = (current_sha[1] != self._backup_firmware_sha[1])
1486 corrupt_VBOOTB = (current_sha[2] != self._backup_firmware_sha[2])
1487 corrupt_FVMAINB = (current_sha[3] != self._backup_firmware_sha[3])
Tom Wai-Hong Tame6232342012-09-24 16:18:01 +08001488 logging.info("Firmware changed:")
Vic Yang772df8a2012-10-31 10:10:49 +08001489 logging.info('VBOOTA is changed: %s', corrupt_VBOOTA)
1490 logging.info('VBOOTB is changed: %s', corrupt_VBOOTB)
1491 logging.info('FVMAIN is changed: %s', corrupt_FVMAIN)
1492 logging.info('FVMAINB is changed: %s', corrupt_FVMAINB)
Tom Wai-Hong Tame6232342012-09-24 16:18:01 +08001493 return True
ctchang38ae4922012-09-03 17:01:16 +08001494
1495
1496 def backup_firmware(self, suffix='.original'):
1497 """Backup firmware to file, and then send it to host.
1498
1499 Args:
1500 suffix: a string appended to backup file name
1501 """
Chun-ting Changd43aa9b2012-11-16 10:12:05 +08001502 remote_temp_dir = self.faft_client.system.create_temp_dir()
1503 self.faft_client.bios.dump_whole(os.path.join(remote_temp_dir, 'bios'))
Chun-ting Chang9380c2c2012-10-05 17:31:05 +08001504 self._client.get_file(os.path.join(remote_temp_dir, 'bios'),
1505 os.path.join(self.resultsdir, 'bios' + suffix))
ctchang38ae4922012-09-03 17:01:16 +08001506
1507 self._backup_firmware_sha = self.get_current_firmware_sha()
Vic Yang772df8a2012-10-31 10:10:49 +08001508 logging.info('Backup firmware stored in %s with suffix %s',
1509 self.resultsdir, suffix)
ctchang38ae4922012-09-03 17:01:16 +08001510
1511
Tom Wai-Hong Tame6232342012-09-24 16:18:01 +08001512 def is_firmware_saved(self):
1513 """Check if a firmware saved (called backup_firmware before).
1514
1515 Returns:
1516 True if the firmware is backuped; otherwise False.
1517 """
1518 return self._backup_firmware_sha != ()
1519
1520
Tom Wai-Hong Tam1dd11592012-10-26 15:01:45 +08001521 def clear_saved_firmware(self):
1522 """Clear the firmware saved by the method backup_firmware."""
1523 self._backup_firmware_sha = ()
1524
1525
ctchang38ae4922012-09-03 17:01:16 +08001526 def restore_firmware(self, suffix='.original'):
1527 """Restore firmware from host in resultsdir.
1528
1529 Args:
1530 suffix: a string appended to backup file name
1531 """
Tom Wai-Hong Tame6232342012-09-24 16:18:01 +08001532 if not self.is_firmware_changed():
ctchang38ae4922012-09-03 17:01:16 +08001533 return
1534
1535 # Backup current corrupted firmware.
1536 self.backup_firmware(suffix='.corrupt')
1537
1538 # Restore firmware.
Chun-ting Changd43aa9b2012-11-16 10:12:05 +08001539 remote_temp_dir = self.faft_client.system.create_temp_dir()
Chun-ting Chang9380c2c2012-10-05 17:31:05 +08001540 self._client.send_file(os.path.join(self.resultsdir, 'bios' + suffix),
1541 os.path.join(remote_temp_dir, 'bios'))
ctchang38ae4922012-09-03 17:01:16 +08001542
Chun-ting Changd43aa9b2012-11-16 10:12:05 +08001543 self.faft_client.bios.write_whole(
1544 os.path.join(remote_temp_dir, 'bios'))
Tom Wai-Hong Tame6232342012-09-24 16:18:01 +08001545 self.sync_and_warm_reboot()
1546 self.wait_for_client_offline()
Tom Wai-Hong Tame2f9cf92012-11-26 10:04:11 +08001547 self.wait_dev_screen_and_ctrl_d()
Tom Wai-Hong Tame6232342012-09-24 16:18:01 +08001548 self.wait_for_client()
1549
ctchang38ae4922012-09-03 17:01:16 +08001550 logging.info('Successfully restore firmware.')
Chun-ting Changf91ee0f2012-09-17 18:31:54 +08001551
1552
1553 def setup_firmwareupdate_shellball(self, shellball=None):
1554 """Deside a shellball to use in firmware update test.
1555
1556 Check if there is a given shellball, and it is a shell script. Then,
1557 send it to the remote host. Otherwise, use
1558 /usr/sbin/chromeos-firmwareupdate.
1559
1560 Args:
1561 shellball: path of a shellball or default to None.
1562
1563 Returns:
1564 Path of shellball in remote host.
1565 If use default shellball, reutrn None.
1566 """
1567 updater_path = None
1568 if shellball:
1569 # Determine the firmware file is a shellball or a raw binary.
1570 is_shellball = (utils.system_output("file %s" % shellball).find(
1571 "shell script") != -1)
1572 if is_shellball:
Vic Yang772df8a2012-10-31 10:10:49 +08001573 logging.info('Device will update firmware with shellball %s',
1574 shellball)
Chun-ting Changd43aa9b2012-11-16 10:12:05 +08001575 temp_dir = self.faft_client.system.create_temp_dir(
1576 'shellball_')
Chun-ting Changf91ee0f2012-09-17 18:31:54 +08001577 temp_shellball = os.path.join(temp_dir, 'updater.sh')
1578 self._client.send_file(shellball, temp_shellball)
1579 updater_path = temp_shellball
1580 else:
1581 raise error.TestFail(
1582 'The given shellball is not a shell script.')
1583 return updater_path