blob: 43ecaee1d8493984d3cd14d99e0a679634649716 [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 Tama70f0fe2011-09-02 18:28:47 +080010import time
Tom Wai-Hong Tama70f0fe2011-09-02 18:28:47 +080011
Tom Wai-Hong Tam76c75072011-10-25 18:00:12 +080012from autotest_lib.client.bin import utils
Tom Wai-Hong Tama70f0fe2011-09-02 18:28:47 +080013from autotest_lib.client.common_lib import error
Tom Wai-Hong Tam6ec46e32012-10-05 16:39:21 +080014from autotest_lib.server.cros import vboot_constants as vboot
Tom Wai-Hong Tam665281c2012-10-30 11:55:10 +080015from autotest_lib.server.cros import chrome_ec
Vic Yangf93f7022012-10-31 09:40:36 +080016from autotest_lib.server.cros.faft_checkers import FAFTCheckers
Vic Yangebd6de62012-06-26 14:25:57 +080017from autotest_lib.server.cros.faft_client_attribute import FAFTClientAttribute
Tom Wai-Hong Tam41738762012-10-29 14:32:39 +080018from autotest_lib.server.cros.faft_delay_constants import FAFTDelayConstants
Tom Wai-Hong Tam22b77302011-11-03 13:03:48 +080019from autotest_lib.server.cros.servo_test import ServoTest
Gediminas Ramanauskasba352ad2012-11-09 09:43:32 -080020from autotest_lib.server import hosts
Tom Wai-Hong Tama70f0fe2011-09-02 18:28:47 +080021
Tom Wai-Hong Tama70f0fe2011-09-02 18:28:47 +080022class FAFTSequence(ServoTest):
23 """
24 The base class of Fully Automated Firmware Test Sequence.
25
26 Many firmware tests require several reboot cycles and verify the resulted
27 system states. To do that, an Autotest test case should detailly handle
28 every action on each step. It makes the test case hard to read and many
29 duplicated code. The base class FAFTSequence is to solve this problem.
30
31 The actions of one reboot cycle is defined in a dict, namely FAFT_STEP.
32 There are four functions in the FAFT_STEP dict:
33 state_checker: a function to check the current is valid or not,
34 returning True if valid, otherwise, False to break the whole
35 test sequence.
36 userspace_action: a function to describe the action ran in userspace.
Tom Wai-Hong Tamb21b6b42012-07-26 10:46:30 +080037 reboot_action: a function to do reboot, default: sync_and_warm_reboot.
Tom Wai-Hong Tama70f0fe2011-09-02 18:28:47 +080038 firmware_action: a function to describe the action ran after reboot.
39
Tom Wai-Hong Tam7c17ff22011-10-26 09:44:09 +080040 And configurations:
41 install_deps_after_boot: if True, install the Autotest dependency after
42 boot; otherwise, do nothing. It is for the cases of recovery mode
43 test. The test boots a USB/SD image instead of an internal image.
44 The previous installed Autotest dependency on the internal image
45 is lost. So need to install it again.
46
Tom Wai-Hong Tama70f0fe2011-09-02 18:28:47 +080047 The default FAFT_STEP checks nothing in state_checker and does nothing in
Tom Wai-Hong Tamf1e34972011-11-02 17:07:04 +080048 userspace_action and firmware_action. Its reboot_action is a hardware
49 reboot. You can change the default FAFT_STEP by calling
Tom Wai-Hong Tama70f0fe2011-09-02 18:28:47 +080050 self.register_faft_template(FAFT_STEP).
51
52 A FAFT test case consists of several FAFT_STEP's, namely FAFT_SEQUENCE.
53 FAFT_SEQUENCE is an array of FAFT_STEP's. Any missing fields on FAFT_STEP
54 fall back to default.
55
56 In the run_once(), it should register and run FAFT_SEQUENCE like:
57 def run_once(self):
58 self.register_faft_sequence(FAFT_SEQUENCE)
59 self.run_faft_sequnce()
60
61 Note that in the last step, we only run state_checker. The
62 userspace_action, reboot_action, and firmware_action are not executed.
63
64 Attributes:
65 _faft_template: The default FAFT_STEP of each step. The actions would
66 be over-written if the registered FAFT_SEQUENCE is valid.
67 _faft_sequence: The registered FAFT_SEQUENCE.
Tom Wai-Hong Tame796de42012-10-16 19:42:20 +080068 _install_image_path: The URL or the path on the host to the Chrome OS
69 test image to be installed.
Tom Wai-Hong Tam1a3ff742012-01-11 16:36:46 +080070 _firmware_update: Boolean. True if firmware update needed after
71 installing the image.
Tom Wai-Hong Tama70f0fe2011-09-02 18:28:47 +080072 """
73 version = 1
74
Tom Wai-Hong Tamcfda61f2011-11-02 17:41:01 +080075 # Mapping of partition number of kernel and rootfs.
76 KERNEL_MAP = {'a':'2', 'b':'4', '2':'2', '4':'4', '3':'2', '5':'4'}
77 ROOTFS_MAP = {'a':'3', 'b':'5', '2':'3', '4':'5', '3':'3', '5':'5'}
78 OTHER_KERNEL_MAP = {'a':'4', 'b':'2', '2':'4', '4':'2', '3':'4', '5':'2'}
79 OTHER_ROOTFS_MAP = {'a':'5', 'b':'3', '2':'5', '4':'3', '3':'5', '5':'3'}
80
Tom Wai-Hong Tam78709592011-12-19 11:16:50 +080081 CHROMEOS_MAGIC = "CHROMEOS"
82 CORRUPTED_MAGIC = "CORRUPTD"
83
Vadim Bendebury89ec24e2012-12-17 12:54:18 -080084 _ROOTFS_PARTITION_NUMBER = 3
85
Tom Wai-Hong Tame796de42012-10-16 19:42:20 +080086 _HTTP_PREFIX = 'http://'
87 _DEVSERVER_PORT = '8090'
88
Tom Wai-Hong Tam109f63c2011-12-08 14:58:27 +080089 _faft_template = {}
Tom Wai-Hong Tama70f0fe2011-09-02 18:28:47 +080090 _faft_sequence = ()
91
Tom Wai-Hong Tam40fd9472012-01-09 17:11:02 +080092 _install_image_path = None
Tom Wai-Hong Tam1a3ff742012-01-11 16:36:46 +080093 _firmware_update = False
Tom Wai-Hong Tam1db43832011-12-09 10:50:56 +080094
ctchang38ae4922012-09-03 17:01:16 +080095 _backup_firmware_sha = ()
96
Tom Wai-Hong Tam01d5e572012-10-23 10:07:11 +080097 # Class level variable, keep track the states of one time setup.
98 # This variable is preserved across tests which inherit this class.
99 _global_setup_done = {
100 'gbb_flags': False,
Tom Wai-Hong Tam73229372012-10-23 11:58:16 +0800101 'reimage': False,
Tom Wai-Hong Tam01d5e572012-10-23 10:07:11 +0800102 'usb_check': False,
103 }
Vic Yang54f70572012-10-19 17:05:26 +0800104
Tom Wai-Hong Tam01d5e572012-10-23 10:07:11 +0800105 @classmethod
106 def check_setup_done(cls, label):
107 """Check if the given setup is done.
Vic Yangdbaba8f2012-10-17 16:05:35 +0800108
Tom Wai-Hong Tam01d5e572012-10-23 10:07:11 +0800109 Args:
110 label: The label of the setup.
111 """
112 return cls._global_setup_done[label]
113
114
115 @classmethod
116 def mark_setup_done(cls, label):
117 """Mark the given setup done.
118
119 Args:
120 label: The label of the setup.
121 """
122 cls._global_setup_done[label] = True
123
124
125 @classmethod
126 def unmark_setup_done(cls, label):
127 """Mark the given setup not done.
128
129 Args:
130 label: The label of the setup.
131 """
132 cls._global_setup_done[label] = False
Vic Yang54f70572012-10-19 17:05:26 +0800133
Tom Wai-Hong Tam1db43832011-12-09 10:50:56 +0800134
135 def initialize(self, host, cmdline_args, use_pyauto=False, use_faft=False):
136 # Parse arguments from command line
137 args = {}
138 for arg in cmdline_args:
139 match = re.search("^(\w+)=(.+)", arg)
140 if match:
141 args[match.group(1)] = match.group(2)
Tom Wai-Hong Tam40fd9472012-01-09 17:11:02 +0800142 if 'image' in args:
143 self._install_image_path = args['image']
Vic Yang772df8a2012-10-31 10:10:49 +0800144 logging.info('Install Chrome OS test image path: %s',
Tom Wai-Hong Tam40fd9472012-01-09 17:11:02 +0800145 self._install_image_path)
Tom Wai-Hong Tam1a3ff742012-01-11 16:36:46 +0800146 if 'firmware_update' in args and args['firmware_update'].lower() \
147 not in ('0', 'false', 'no'):
148 if self._install_image_path:
149 self._firmware_update = True
150 logging.info('Also update firmware after installing.')
151 else:
152 logging.warning('Firmware update will not not performed '
153 'since no image is specified.')
Tom Wai-Hong Tam1db43832011-12-09 10:50:56 +0800154
155 super(FAFTSequence, self).initialize(host, cmdline_args, use_pyauto,
156 use_faft)
Vic Yangebd6de62012-06-26 14:25:57 +0800157 if use_faft:
158 self.client_attr = FAFTClientAttribute(
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800159 self.faft_client.system.get_platform_name())
Tom Wai-Hong Tam41738762012-10-29 14:32:39 +0800160 self.delay = FAFTDelayConstants(
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800161 self.faft_client.system.get_platform_name())
Vic Yangf93f7022012-10-31 09:40:36 +0800162 self.checkers = FAFTCheckers(self, self.faft_client)
Tom Wai-Hong Tam1db43832011-12-09 10:50:56 +0800163
Tom Wai-Hong Tam6019a1a2012-10-12 14:03:34 +0800164 if self.client_attr.chrome_ec:
Tom Wai-Hong Tam665281c2012-10-30 11:55:10 +0800165 self.ec = chrome_ec.ChromeEC(self.servo)
Tom Wai-Hong Tam6019a1a2012-10-12 14:03:34 +0800166
Tom Wai-Hong Tam9c15b4b2012-10-29 17:59:26 +0800167 if not self.client_attr.has_keyboard:
168 # The environment variable USBKM232_UART_DEVICE should point
169 # to the USB-KM232 UART device.
170 if ('USBKM232_UART_DEVICE' not in os.environ or
171 not os.path.exists(os.environ['USBKM232_UART_DEVICE'])):
172 raise error.TestError('Must set a valid environment '
173 'variable USBKM232_UART_DEVICE.')
174
Gediminas Ramanauskas3297d4f2012-09-10 15:30:10 -0700175 # Setting up key matrix mapping
176 self.servo.set_key_matrix(self.client_attr.key_matrix_layout)
177
Tom Wai-Hong Tamc5c14ef2012-11-20 16:33:37 +0800178 self._host = None
179 if (self.client_attr.broken_rec_mode and
180 self.servo.get_target_hostname()):
181 self._host = hosts.create_host(self.servo.get_target_hostname())
Gediminas Ramanauskasba352ad2012-11-09 09:43:32 -0800182
Tom Wai-Hong Tama70f0fe2011-09-02 18:28:47 +0800183
Tom Wai-Hong Tam700c9fd2012-11-15 18:18:30 +0800184 def setup(self, ec_wp=None):
Tom Wai-Hong Tama70f0fe2011-09-02 18:28:47 +0800185 """Autotest setup function."""
186 super(FAFTSequence, self).setup()
Tom Wai-Hong Tama70f0fe2011-09-02 18:28:47 +0800187 self.register_faft_template({
188 'state_checker': (None),
189 'userspace_action': (None),
Tom Wai-Hong Tamb21b6b42012-07-26 10:46:30 +0800190 'reboot_action': (self.sync_and_warm_reboot),
Tom Wai-Hong Tama70f0fe2011-09-02 18:28:47 +0800191 'firmware_action': (None)
192 })
Tom Wai-Hong Tam19ad9682012-10-24 09:33:42 +0800193 self.install_test_image(self._install_image_path, self._firmware_update)
Tom Wai-Hong Tamb92669c2012-11-29 13:57:11 +0800194 self.record_system_info()
Tom Wai-Hong Tam01d5e572012-10-23 10:07:11 +0800195 self.setup_gbb_flags()
Tom Wai-Hong Tam700c9fd2012-11-15 18:18:30 +0800196 self.setup_ec_write_protect(ec_wp)
Tom Wai-Hong Tama70f0fe2011-09-02 18:28:47 +0800197
198
199 def cleanup(self):
200 """Autotest cleanup function."""
Tom Wai-Hong Tam700c9fd2012-11-15 18:18:30 +0800201 self.restore_ec_write_protect()
Tom Wai-Hong Tama70f0fe2011-09-02 18:28:47 +0800202 self._faft_sequence = ()
Tom Wai-Hong Tam109f63c2011-12-08 14:58:27 +0800203 self._faft_template = {}
Tom Wai-Hong Tama70f0fe2011-09-02 18:28:47 +0800204 super(FAFTSequence, self).cleanup()
205
206
Tom Wai-Hong Tamb92669c2012-11-29 13:57:11 +0800207 def record_system_info(self):
208 """Record some critical system info to the attr keyval.
209
210 This info is used by generate_test_report and local_dash later.
211 """
212 self.write_attr_keyval({
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800213 'fw_version': self.faft_client.ec.get_version(),
214 'hwid': self.faft_client.system.get_crossystem_value('hwid'),
215 'fwid': self.faft_client.system.get_crossystem_value('fwid'),
Tom Wai-Hong Tamb92669c2012-11-29 13:57:11 +0800216 })
217
218
Tom Wai-Hong Tam01d5e572012-10-23 10:07:11 +0800219 def invalidate_firmware_setup(self):
220 """Invalidate all firmware related setup state.
Vic Yangdbaba8f2012-10-17 16:05:35 +0800221
Tom Wai-Hong Tam01d5e572012-10-23 10:07:11 +0800222 This method is called when the firmware is re-flashed. It resets all
223 firmware related setup states so that the next test setup properly
224 again.
Vic Yangdbaba8f2012-10-17 16:05:35 +0800225 """
Tom Wai-Hong Tam01d5e572012-10-23 10:07:11 +0800226 self.unmark_setup_done('gbb_flags')
Vic Yangdbaba8f2012-10-17 16:05:35 +0800227
228
Tom Wai-Hong Tamc285f4c2012-10-30 15:44:39 +0800229 def _retrieve_recovery_reason_from_trap(self):
230 """Try to retrieve the recovery reason from a trapped recovery screen.
Tom Wai-Hong Tame6232342012-09-24 16:18:01 +0800231
Tom Wai-Hong Tamc285f4c2012-10-30 15:44:39 +0800232 Returns:
233 The recovery_reason, 0 if any error.
Tom Wai-Hong Tame6232342012-09-24 16:18:01 +0800234 """
Tom Wai-Hong Tamc285f4c2012-10-30 15:44:39 +0800235 recovery_reason = 0
Tom Wai-Hong Tam4bb85e22012-10-25 14:35:24 +0800236 logging.info('Try to retrieve recovery reason...')
Vadim Bendeburye7bd9362012-12-19 14:35:20 -0800237 if self.servo.get_usbkey_direction() == 'dut':
Tom Wai-Hong Tam4bb85e22012-10-25 14:35:24 +0800238 self.wait_fw_screen_and_plug_usb()
239 else:
Vadim Bendeburye7bd9362012-12-19 14:35:20 -0800240 self.servo.switch_usbkey('dut')
Tom Wai-Hong Tam4bb85e22012-10-25 14:35:24 +0800241
242 try:
243 self.wait_for_client(install_deps=True)
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800244 lines = self.faft_client.system.run_shell_command_get_output(
Tom Wai-Hong Tam4bb85e22012-10-25 14:35:24 +0800245 'crossystem recovery_reason')
Tom Wai-Hong Tamc285f4c2012-10-30 15:44:39 +0800246 recovery_reason = int(lines[0])
247 logging.info('Got the recovery reason %d.', recovery_reason)
Tom Wai-Hong Tam4bb85e22012-10-25 14:35:24 +0800248 except AssertionError:
249 logging.info('Failed to get the recovery reason.')
Tom Wai-Hong Tamc285f4c2012-10-30 15:44:39 +0800250 return recovery_reason
Tom Wai-Hong Tam4bb85e22012-10-25 14:35:24 +0800251
Tom Wai-Hong Tamc285f4c2012-10-30 15:44:39 +0800252
253 def _reset_client(self):
254 """Reset client to a workable state.
255
256 This method is called when the client is not responsive. It may be
257 caused by the following cases:
258 - halt on a firmware screen without timeout, e.g. REC_INSERT screen;
259 - corrupted firmware;
260 - corrutped OS image.
261 """
Tom Wai-Hong Tame6232342012-09-24 16:18:01 +0800262 # DUT may halt on a firmware screen. Try cold reboot.
263 logging.info('Try cold reboot...')
264 self.cold_reboot()
Tom Wai-Hong Tame2f9cf92012-11-26 10:04:11 +0800265 self.wait_for_client_offline()
266 self.wait_dev_screen_and_ctrl_d()
Tom Wai-Hong Tame6232342012-09-24 16:18:01 +0800267 try:
Vic Yang8eaf5ad2012-09-13 14:05:37 +0800268 self.wait_for_client()
Tom Wai-Hong Tame6232342012-09-24 16:18:01 +0800269 return
270 except AssertionError:
271 pass
272
273 # DUT may be broken by a corrupted firmware. Restore firmware.
274 # We assume the recovery boot still works fine. Since the recovery
275 # code is in RO region and all FAFT tests don't change the RO region
276 # except GBB.
277 if self.is_firmware_saved():
Tom Wai-Hong Tamc285f4c2012-10-30 15:44:39 +0800278 self._ensure_client_in_recovery()
Tom Wai-Hong Tame6232342012-09-24 16:18:01 +0800279 logging.info('Try restore the original firmware...')
280 if self.is_firmware_changed():
281 try:
282 self.restore_firmware()
283 return
284 except AssertionError:
285 logging.info('Restoring firmware doesn\'t help.')
286
287 # DUT may be broken by a corrupted OS image. Restore OS image.
Tom Wai-Hong Tamc285f4c2012-10-30 15:44:39 +0800288 self._ensure_client_in_recovery()
Tom Wai-Hong Tame6232342012-09-24 16:18:01 +0800289 logging.info('Try restore the OS image...')
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800290 self.faft_client.system.run_shell_command('chromeos-install --yes')
Tom Wai-Hong Tame6232342012-09-24 16:18:01 +0800291 self.sync_and_warm_reboot()
292 self.wait_for_client_offline()
Tom Wai-Hong Tame2f9cf92012-11-26 10:04:11 +0800293 self.wait_dev_screen_and_ctrl_d()
Tom Wai-Hong Tame6232342012-09-24 16:18:01 +0800294 try:
295 self.wait_for_client(install_deps=True)
296 logging.info('Successfully restore OS image.')
297 return
298 except AssertionError:
299 logging.info('Restoring OS image doesn\'t help.')
300
301
Tom Wai-Hong Tamc285f4c2012-10-30 15:44:39 +0800302 def _ensure_client_in_recovery(self):
Tom Wai-Hong Tame6232342012-09-24 16:18:01 +0800303 """Ensure client in recovery boot; reboot into it if necessary.
304
305 Raises:
306 error.TestError: if failed to boot the USB image.
307 """
308 # DUT works fine and is already in recovery boot, done.
309 if self._ping_test(self._client.ip, timeout=5):
Vic Yangf93f7022012-10-31 09:40:36 +0800310 if self.checkers.crossystem_checker({'mainfw_type': 'recovery'}):
Tom Wai-Hong Tame6232342012-09-24 16:18:01 +0800311 return
312
313 logging.info('Try boot into USB image...')
Vadim Bendeburye7bd9362012-12-19 14:35:20 -0800314 self.servo.switch_usbkey('host')
Tom Wai-Hong Tame6232342012-09-24 16:18:01 +0800315 self.enable_rec_mode_and_reboot()
316 self.wait_fw_screen_and_plug_usb()
317 try:
318 self.wait_for_client(install_deps=True)
319 except AssertionError:
320 raise error.TestError('Failed to boot the USB image.')
Vic Yang8eaf5ad2012-09-13 14:05:37 +0800321
322
Tom Wai-Hong Tamc285f4c2012-10-30 15:44:39 +0800323 def _restore_routine_from_timeout(self, next_step=None):
324 """A routine to try to restore the system from a timeout error.
325
326 This method is called when FAFT failed to connect DUT after reboot.
327
328 Args:
329 next_step: Optional, a FAFT_STEP dict of the next step, which is used
330 for diagnostic.
331
332 Raises:
333 error.TestFail: This exception is already raised, with a decription
334 why it failed.
335 """
336 next_checker_matched = False
337 if next_step is not None:
338 next_test = {}
339 next_test.update(self._faft_template)
340 next_test.update(next_step)
341
342 # TODO(waihong@chromium.org): Implement replugging the Ethernet to
343 # identify if it is a network flaky.
344
345 recovery_reason = self._retrieve_recovery_reason_from_trap()
346 if next_step is not None and recovery_reason:
347 if self._call_action(next_test['state_checker']):
348 # Repluging the USB can pass the state_checker of the next step,
349 # meaning that the firmware failed to boot into USB directly.
350 next_checker_matched = True
351
352 # Reset client to a workable state.
353 self._reset_client()
354
355 # Raise the proper TestFail exception.
356 if next_checker_matched:
357 raise error.TestFail('Firmware failed to auto-boot USB in the '
Tom Wai-Hong Tam66648432012-11-07 10:06:00 +0800358 'recovery boot (reason: %d)' % recovery_reason)
Tom Wai-Hong Tamc285f4c2012-10-30 15:44:39 +0800359 elif recovery_reason:
Tom Wai-Hong Tam66648432012-11-07 10:06:00 +0800360 raise error.TestFail('Trapped in the recovery screen (reason: %d) '
361 'and timed out' % recovery_reason)
Tom Wai-Hong Tamc285f4c2012-10-30 15:44:39 +0800362 else:
Tom Wai-Hong Tam66648432012-11-07 10:06:00 +0800363 raise error.TestFail('Timed out waiting for DUT reboot')
Tom Wai-Hong Tamc285f4c2012-10-30 15:44:39 +0800364
365
Tom Wai-Hong Tama6b382c2012-11-14 09:31:02 +0800366 def assert_test_image_in_usb_disk(self, usb_dev=None, install_shim=False):
Tom Wai-Hong Tam76c75072011-10-25 18:00:12 +0800367 """Assert an USB disk plugged-in on servo and a test image inside.
368
Tom Wai-Hong Tam91f49822011-12-28 15:44:15 +0800369 Args:
370 usb_dev: A string of USB stick path on the host, like '/dev/sdc'.
371 If None, it is detected automatically.
Tom Wai-Hong Tama6b382c2012-11-14 09:31:02 +0800372 install_shim: True to verify an install shim instead of a test image.
Tom Wai-Hong Tam91f49822011-12-28 15:44:15 +0800373
Tom Wai-Hong Tam76c75072011-10-25 18:00:12 +0800374 Raises:
Tom Wai-Hong Tama6b382c2012-11-14 09:31:02 +0800375 error.TestError: if USB disk not detected or not a test (install shim)
376 image.
Tom Wai-Hong Tam76c75072011-10-25 18:00:12 +0800377 """
Tom Wai-Hong Tam01d5e572012-10-23 10:07:11 +0800378 if self.check_setup_done('usb_check'):
Vic Yang54f70572012-10-19 17:05:26 +0800379 return
Tom Wai-Hong Tam91f49822011-12-28 15:44:15 +0800380 if usb_dev:
Vadim Bendeburye7bd9362012-12-19 14:35:20 -0800381 assert self.servo.get_usbkey_direction() == 'host'
Tom Wai-Hong Tam91f49822011-12-28 15:44:15 +0800382 else:
Vadim Bendeburye7bd9362012-12-19 14:35:20 -0800383 self.servo.switch_usbkey('host')
Tom Wai-Hong Tam91f49822011-12-28 15:44:15 +0800384 usb_dev = self.servo.probe_host_usb_dev()
385 if not usb_dev:
386 raise error.TestError(
387 'An USB disk should be plugged in the servo board.')
Vadim Bendebury89ec24e2012-12-17 12:54:18 -0800388
389 rootfs = '%s%s' % (usb_dev, self._ROOTFS_PARTITION_NUMBER)
390 logging.info('usb dev is %s', usb_dev)
391 tmpd = self.servo.system_output('mktemp -d -t usbcheck.XXXX')
392 self.servo.system('mount -o ro %s %s' % (rootfs, tmpd))
393
394 if install_shim:
395 dir_list = self.servo.system_output('ls -a %s' %
396 os.path.join(tmpd, 'root'))
397 check_passed = '.factory_installer' in dir_list
398 else:
399 check_passed = self.servo.system_output(
400 'grep -i "CHROMEOS_RELEASE_DESCRIPTION=.*test" %s' %
401 os.path.join(tmpd, 'etc/lsb-release'),
402 ignore_status=True)
403 for cmd in ('umount %s' % rootfs, 'sync', 'rm -rf %s' % tmpd):
404 self.servo.system(cmd)
405
406 if not check_passed:
407 raise error.TestError(
408 'No Chrome OS %s found on the USB flash plugged into servo' %
409 'install shim' if install_shim else 'test')
410
Tom Wai-Hong Tam01d5e572012-10-23 10:07:11 +0800411 self.mark_setup_done('usb_check')
Tom Wai-Hong Tam76c75072011-10-25 18:00:12 +0800412
413
Tom Wai-Hong Tama6b382c2012-11-14 09:31:02 +0800414 def setup_usbkey(self, usbkey, host=None, install_shim=False):
Tom Wai-Hong Tam893bcc02012-11-02 16:13:34 +0800415 """Setup the USB disk for the test.
416
417 It checks the setup of USB disk and a valid ChromeOS test image inside.
418 It also muxes the USB disk to either the host or DUT by request.
419
420 Args:
421 usbkey: True if the USB disk is required for the test, False if not
422 required.
423 host: Optional, True to mux the USB disk to host, False to mux it
424 to DUT, default to do nothing.
Tom Wai-Hong Tama6b382c2012-11-14 09:31:02 +0800425 install_shim: True to verify an install shim instead of a test image.
Tom Wai-Hong Tam893bcc02012-11-02 16:13:34 +0800426 """
427 if usbkey:
Tom Wai-Hong Tama6b382c2012-11-14 09:31:02 +0800428 self.assert_test_image_in_usb_disk(install_shim=install_shim)
Tom Wai-Hong Tam893bcc02012-11-02 16:13:34 +0800429 elif host is None:
430 # USB disk is not required for the test. Better to mux it to host.
431 host = True
432
433 if host is True:
Vadim Bendeburye7bd9362012-12-19 14:35:20 -0800434 self.servo.switch_usbkey('host')
Tom Wai-Hong Tam893bcc02012-11-02 16:13:34 +0800435 elif host is False:
Vadim Bendeburye7bd9362012-12-19 14:35:20 -0800436 self.servo.switch_usbkey('dut')
Tom Wai-Hong Tam893bcc02012-11-02 16:13:34 +0800437
438
Tom Wai-Hong Tame796de42012-10-16 19:42:20 +0800439 def get_server_address(self):
440 """Get the server address seen from the client.
441
442 Returns:
443 A string of the server address.
444 """
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800445 r = self.faft_client.system.run_shell_command_get_output(
446 "echo $SSH_CLIENT")
Tom Wai-Hong Tame796de42012-10-16 19:42:20 +0800447 return r[0].split()[0]
448
449
Simran Basi741b5d42012-05-18 11:27:15 -0700450 def install_test_image(self, image_path=None, firmware_update=False):
Tom Wai-Hong Tam40fd9472012-01-09 17:11:02 +0800451 """Install the test image specied by the path onto the USB and DUT disk.
452
453 The method first copies the image to USB disk and reboots into it via
Mike Truty49153d82012-08-21 22:27:30 -0500454 recovery mode. Then runs 'chromeos-install' (and possible
455 chromeos-firmwareupdate') to install it to DUT disk.
456
457 Sample command line:
458
459 run_remote_tests.sh --servo --board=daisy --remote=w.x.y.z \
460 --args="image=/tmp/chromiumos_test_image.bin firmware_update=True" \
461 server/site_tests/firmware_XXXX/control
462
463 This test requires an automated recovery to occur while simulating
464 inserting and removing the usb key from the servo. To allow this the
465 following hardware setup is required:
466 1. servo2 board connected via servoflex.
467 2. USB key inserted in the servo2.
468 3. servo2 connected to the dut via dut_hub_in in the usb 2.0 slot.
469 4. network connected via usb dongle in the dut in usb 3.0 slot.
Tom Wai-Hong Tam40fd9472012-01-09 17:11:02 +0800470
471 Args:
Tom Wai-Hong Tame796de42012-10-16 19:42:20 +0800472 image_path: An URL or a path on the host to the test image.
Tom Wai-Hong Tam1a3ff742012-01-11 16:36:46 +0800473 firmware_update: Also update the firmware after installing.
Tom Wai-Hong Tam71818d82012-10-24 14:57:43 +0800474
475 Raises:
476 error.TestError: If devserver failed to start.
Tom Wai-Hong Tam40fd9472012-01-09 17:11:02 +0800477 """
Tom Wai-Hong Tam19ad9682012-10-24 09:33:42 +0800478 if not image_path:
479 return
480
Tom Wai-Hong Tam73229372012-10-23 11:58:16 +0800481 if self.check_setup_done('reimage'):
482 return
483
Tom Wai-Hong Tame796de42012-10-16 19:42:20 +0800484 if image_path.startswith(self._HTTP_PREFIX):
485 # TODO(waihong@chromium.org): Add the check of the URL to ensure
486 # it is a test image.
487 devserver = None
488 image_url = image_path
Tom Wai-Hong Tam42f136d2012-10-26 11:11:23 +0800489 elif self.servo.is_localhost():
Tom Wai-Hong Tam42f136d2012-10-26 11:11:23 +0800490 # If servod is localhost, i.e. both servod and FAFT see the same
491 # file system, do nothing.
492 devserver = None
493 image_url = image_path
Tom Wai-Hong Tame796de42012-10-16 19:42:20 +0800494 else:
Tom Wai-Hong Tame796de42012-10-16 19:42:20 +0800495 image_dir, image_base = os.path.split(image_path)
496 logging.info('Starting devserver to serve the image...')
497 # The following stdout and stderr arguments should not be None,
498 # even we don't use them. Otherwise, the socket of devserve is
499 # created as fd 1 (as no stdout) but it still thinks stdout is fd
500 # 1 and dump the log to the socket. Wrong HTTP protocol happens.
Tom Wai-Hong Tam71818d82012-10-24 14:57:43 +0800501 devserver = subprocess.Popen(['/usr/lib/devserver/devserver.py',
Tom Wai-Hong Tame796de42012-10-16 19:42:20 +0800502 '--archive_dir=%s' % image_dir,
503 '--port=%s' % self._DEVSERVER_PORT],
504 stdout=subprocess.PIPE,
505 stderr=subprocess.PIPE)
506 image_url = '%s%s:%s/static/archive/%s' % (
507 self._HTTP_PREFIX,
508 self.get_server_address(),
509 self._DEVSERVER_PORT,
510 image_base)
511
Tom Wai-Hong Tam71818d82012-10-24 14:57:43 +0800512 # Wait devserver startup completely
Tom Wai-Hong Tam41738762012-10-29 14:32:39 +0800513 time.sleep(self.delay.devserver)
Tom Wai-Hong Tam71818d82012-10-24 14:57:43 +0800514 # devserver is a service running forever. If it is terminated,
515 # some error does happen.
516 if devserver.poll():
517 raise error.TestError('Starting devserver failed, '
518 'returning %d.' % devserver.returncode)
519
Vic Yang772df8a2012-10-31 10:10:49 +0800520 logging.info('Ask Servo to install the image from %s', image_url)
Tom Wai-Hong Tame796de42012-10-16 19:42:20 +0800521 self.servo.image_to_servo_usb(image_url)
522
Vadim Bendebury89ec24e2012-12-17 12:54:18 -0800523 self.assert_test_image_in_usb_disk()
524
Tom Wai-Hong Tame796de42012-10-16 19:42:20 +0800525 if devserver and devserver.poll() is None:
526 logging.info('Shutting down devserver...')
527 devserver.terminate()
Mike Truty49153d82012-08-21 22:27:30 -0500528
529 # DUT is powered off while imaging servo USB.
530 # Now turn it on.
531 self.servo.power_short_press()
532 self.wait_for_client()
Vadim Bendeburye7bd9362012-12-19 14:35:20 -0800533 self.servo.switch_usbkey('dut')
Mike Truty49153d82012-08-21 22:27:30 -0500534
535 install_cmd = 'chromeos-install --yes'
536 if firmware_update:
537 install_cmd += ' && chromeos-firmwareupdate --mode recovery'
Tom Wai-Hong Tam1dd11592012-10-26 15:01:45 +0800538 self.backup_firmware()
Mike Truty49153d82012-08-21 22:27:30 -0500539
540 self.register_faft_sequence((
541 { # Step 1, request recovery boot
Vic Yangf93f7022012-10-31 09:40:36 +0800542 'state_checker': (self.checkers.crossystem_checker, {
Mike Truty49153d82012-08-21 22:27:30 -0500543 'mainfw_type': ('developer', 'normal'),
544 }),
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800545 'userspace_action': (
546 self.faft_client.system.request_recovery_boot),
Mike Truty49153d82012-08-21 22:27:30 -0500547 'firmware_action': self.wait_fw_screen_and_plug_usb,
548 'install_deps_after_boot': True,
549 },
550 { # Step 2, expected recovery boot
Vic Yangf93f7022012-10-31 09:40:36 +0800551 'state_checker': (self.checkers.crossystem_checker, {
Mike Truty49153d82012-08-21 22:27:30 -0500552 'mainfw_type': 'recovery',
Tom Wai-Hong Tam6ec46e32012-10-05 16:39:21 +0800553 'recovery_reason' : vboot.RECOVERY_REASON['US_TEST'],
Mike Truty49153d82012-08-21 22:27:30 -0500554 }),
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800555 'userspace_action': (self.faft_client.system.run_shell_command,
Mike Truty49153d82012-08-21 22:27:30 -0500556 install_cmd),
557 'reboot_action': self.cold_reboot,
558 'install_deps_after_boot': True,
559 },
560 { # Step 3, expected normal or developer boot (not recovery)
Vic Yangf93f7022012-10-31 09:40:36 +0800561 'state_checker': (self.checkers.crossystem_checker, {
Mike Truty49153d82012-08-21 22:27:30 -0500562 'mainfw_type': ('developer', 'normal')
563 }),
564 },
565 ))
566 self.run_faft_sequence()
Tom Wai-Hong Tam1dd11592012-10-26 15:01:45 +0800567
568 if firmware_update:
569 self.clear_saved_firmware()
570
Mike Truty49153d82012-08-21 22:27:30 -0500571 # 'Unplug' any USB keys in the servo from the dut.
Vadim Bendeburye7bd9362012-12-19 14:35:20 -0800572 self.servo.switch_usbkey('host')
Tom Wai-Hong Tam6668b762012-10-23 11:45:36 +0800573 # Mark usb_check done so it won't check a test image in USB anymore.
574 self.mark_setup_done('usb_check')
Tom Wai-Hong Tam73229372012-10-23 11:58:16 +0800575 self.mark_setup_done('reimage')
Tom Wai-Hong Tam40fd9472012-01-09 17:11:02 +0800576
577
Tom Wai-Hong Tamfa3142e2012-08-16 11:53:58 +0800578 def clear_set_gbb_flags(self, clear_mask, set_mask):
579 """Clear and set the GBB flags in the current flashrom.
Tom Wai-Hong Tam15ce5812012-07-26 14:14:18 +0800580
581 Args:
Tom Wai-Hong Tamfa3142e2012-08-16 11:53:58 +0800582 clear_mask: A mask of flags to be cleared.
583 set_mask: A mask of flags to be set.
Tom Wai-Hong Tam15ce5812012-07-26 14:14:18 +0800584 """
Tom Wai-Hong Tamc1a569f2012-12-04 15:07:25 +0800585 gbb_flags = self.faft_client.bios.get_gbb_flags()
Tom Wai-Hong Tamfa3142e2012-08-16 11:53:58 +0800586 new_flags = gbb_flags & ctypes.c_uint32(~clear_mask).value | set_mask
587
588 if (gbb_flags != new_flags):
Vic Yang772df8a2012-10-31 10:10:49 +0800589 logging.info('Change the GBB flags from 0x%x to 0x%x.',
590 gbb_flags, new_flags)
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800591 self.faft_client.system.run_shell_command(
Tom Wai-Hong Tamfda76e22012-08-08 17:19:10 +0800592 '/usr/share/vboot/bin/set_gbb_flags.sh 0x%x' % new_flags)
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800593 self.faft_client.bios.reload()
Tom Wai-Hong Tama2481922012-08-08 17:24:42 +0800594 # If changing FORCE_DEV_SWITCH_ON flag, reboot to get a clear state
Tom Wai-Hong Tam6ec46e32012-10-05 16:39:21 +0800595 if ((gbb_flags ^ new_flags) & vboot.GBB_FLAG_FORCE_DEV_SWITCH_ON):
Tom Wai-Hong Tama2481922012-08-08 17:24:42 +0800596 self.run_faft_step({
Tom Wai-Hong Tam56977782012-11-23 16:13:28 +0800597 'firmware_action': self.wait_dev_screen_and_ctrl_d,
Tom Wai-Hong Tama2481922012-08-08 17:24:42 +0800598 })
Tom Wai-Hong Tam15ce5812012-07-26 14:14:18 +0800599
600
Vic Yang772df8a2012-10-31 10:10:49 +0800601 def check_ec_capability(self, required_cap=None, suppress_warning=False):
Vic Yang4d72cb62012-07-24 11:51:09 +0800602 """Check if current platform has required EC capabilities.
603
604 Args:
605 required_cap: A list containing required EC capabilities. Pass in
606 None to only check for presence of Chrome EC.
Tom Wai-Hong Tamb8a91392012-09-27 10:45:32 +0800607 suppress_warning: True to suppress any warning messages.
Vic Yang4d72cb62012-07-24 11:51:09 +0800608
609 Returns:
610 True if requirements are met. Otherwise, False.
611 """
612 if not self.client_attr.chrome_ec:
Tom Wai-Hong Tamb8a91392012-09-27 10:45:32 +0800613 if not suppress_warning:
614 logging.warn('Requires Chrome EC to run this test.')
Vic Yang4d72cb62012-07-24 11:51:09 +0800615 return False
616
Vic Yang772df8a2012-10-31 10:10:49 +0800617 if not required_cap:
618 return True
619
Vic Yang4d72cb62012-07-24 11:51:09 +0800620 for cap in required_cap:
621 if cap not in self.client_attr.ec_capability:
Tom Wai-Hong Tamb8a91392012-09-27 10:45:32 +0800622 if not suppress_warning:
623 logging.warn('Requires EC capability "%s" to run this '
Vic Yang772df8a2012-10-31 10:10:49 +0800624 'test.', cap)
Vic Yang4d72cb62012-07-24 11:51:09 +0800625 return False
626
627 return True
628
629
Tom Wai-Hong Tam07278c22012-02-08 16:53:00 +0800630 def check_root_part_on_non_recovery(self, part):
631 """Check the partition number of root device and on normal/dev boot.
632
633 Returns:
634 True if the root device matched and on normal/dev boot;
635 otherwise, False.
636 """
Vic Yangf93f7022012-10-31 09:40:36 +0800637 return self.checkers.root_part_checker(part) and \
638 self.checkers.crossystem_checker({
Tom Wai-Hong Tam07278c22012-02-08 16:53:00 +0800639 'mainfw_type': ('normal', 'developer'),
Tom Wai-Hong Tam07278c22012-02-08 16:53:00 +0800640 })
641
642
Tom Wai-Hong Tamf2103be2011-11-10 07:26:56 +0800643 def _join_part(self, dev, part):
644 """Return a concatenated string of device and partition number.
645
646 Args:
647 dev: A string of device, e.g.'/dev/sda'.
648 part: A string of partition number, e.g.'3'.
649
650 Returns:
651 A concatenated string of device and partition number, e.g.'/dev/sda3'.
652
653 >>> seq = FAFTSequence()
654 >>> seq._join_part('/dev/sda', '3')
655 '/dev/sda3'
656 >>> seq._join_part('/dev/mmcblk0', '2')
657 '/dev/mmcblk0p2'
658 """
659 if 'mmcblk' in dev:
660 return dev + 'p' + part
661 else:
662 return dev + part
663
664
Tom Wai-Hong Tamcfda61f2011-11-02 17:41:01 +0800665 def copy_kernel_and_rootfs(self, from_part, to_part):
666 """Copy kernel and rootfs from from_part to to_part.
667
668 Args:
669 from_part: A string of partition number to be copied from.
Tom Wai-Hong Tamf2103be2011-11-10 07:26:56 +0800670 to_part: A string of partition number to be copied to.
Tom Wai-Hong Tamcfda61f2011-11-02 17:41:01 +0800671 """
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800672 root_dev = self.faft_client.system.get_root_dev()
Vic Yang772df8a2012-10-31 10:10:49 +0800673 logging.info('Copying kernel from %s to %s. Please wait...',
Vic Yang55f31252012-11-01 17:07:54 +0800674 from_part, to_part)
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800675 self.faft_client.system.run_shell_command('dd if=%s of=%s bs=4M' %
Tom Wai-Hong Tamf2103be2011-11-10 07:26:56 +0800676 (self._join_part(root_dev, self.KERNEL_MAP[from_part]),
677 self._join_part(root_dev, self.KERNEL_MAP[to_part])))
Vic Yang772df8a2012-10-31 10:10:49 +0800678 logging.info('Copying rootfs 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.ROOTFS_MAP[from_part]),
682 self._join_part(root_dev, self.ROOTFS_MAP[to_part])))
Tom Wai-Hong Tamcfda61f2011-11-02 17:41:01 +0800683
684
685 def ensure_kernel_boot(self, part):
686 """Ensure the request kernel boot.
687
688 If not, it duplicates the current kernel to the requested kernel
689 and sets the requested higher priority to ensure it boot.
690
691 Args:
Tom Wai-Hong Tama9c1a502011-11-10 06:39:26 +0800692 part: A string of kernel partition number or 'a'/'b'.
Tom Wai-Hong Tamcfda61f2011-11-02 17:41:01 +0800693 """
Vic Yangf93f7022012-10-31 09:40:36 +0800694 if not self.checkers.root_part_checker(part):
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800695 if self.faft_client.kernel.diff_a_b():
Tom Wai-Hong Tam622d0ba2012-08-15 16:29:05 +0800696 self.copy_kernel_and_rootfs(
697 from_part=self.OTHER_KERNEL_MAP[part],
698 to_part=part)
Tom Wai-Hong Tamc7ecfca2011-12-06 11:12:31 +0800699 self.run_faft_step({
700 'userspace_action': (self.reset_and_prioritize_kernel, part),
701 })
Tom Wai-Hong Tamcfda61f2011-11-02 17:41:01 +0800702
703
Tom Wai-Hong Tam05574ee2012-10-30 11:34:21 +0800704 def set_hardware_write_protect(self, enable):
Vic Yang2cabf812012-08-28 02:39:04 +0800705 """Set hardware write protect pin.
706
707 Args:
708 enable: True if asserting write protect pin. Otherwise, False.
709 """
710 self.servo.set('fw_wp_vref', self.client_attr.wp_voltage)
711 self.servo.set('fw_wp_en', 'on')
Tom Wai-Hong Tam05574ee2012-10-30 11:34:21 +0800712 self.servo.set('fw_wp', 'on' if enable else 'off')
Vic Yang416f2032012-08-28 10:18:03 +0800713
714
Tom Wai-Hong Tam44204b32012-11-20 13:55:40 +0800715 def set_ec_write_protect_and_reboot(self, enable):
Vic Yang416f2032012-08-28 10:18:03 +0800716 """Set EC write protect status and reboot to take effect.
717
Tom Wai-Hong Tam44204b32012-11-20 13:55:40 +0800718 The write protect state is only activated if both hardware write
719 protect pin is asserted and software write protect flag is set.
Vic Yang416f2032012-08-28 10:18:03 +0800720 This method asserts/deasserts hardware write protect pin first, and
721 set corresponding EC software write protect flag.
722
Tom Wai-Hong Tam44204b32012-11-20 13:55:40 +0800723 If the device uses non-Chrome EC, set the software write protect via
724 flashrom.
725
726 If the device uses Chrome EC, a reboot is required for write protect
727 to take effect. Since the software write protect flag cannot be unset
728 if hardware write protect pin is asserted, we need to deasserted the
729 pin first if we are deactivating write protect. Similarly, a reboot
730 is required before we can modify the software flag.
731
Vic Yang416f2032012-08-28 10:18:03 +0800732 Args:
733 enable: True if activating EC write protect. Otherwise, False.
734 """
Tom Wai-Hong Tam05574ee2012-10-30 11:34:21 +0800735 self.set_hardware_write_protect(enable)
Tom Wai-Hong Tam44204b32012-11-20 13:55:40 +0800736 if self.client_attr.chrome_ec:
737 self.set_chrome_ec_write_protect_and_reboot(enable)
738 else:
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800739 self.faft_client.ec.set_write_protect(enable)
Tom Wai-Hong Tam44204b32012-11-20 13:55:40 +0800740 self.sync_and_warm_reboot()
741
742
743 def set_chrome_ec_write_protect_and_reboot(self, enable):
744 """Set Chrome EC write protect status and reboot to take effect.
745
746 Args:
747 enable: True if activating EC write protect. Otherwise, False.
748 """
Tom Wai-Hong Tam05574ee2012-10-30 11:34:21 +0800749 if enable:
Vic Yang416f2032012-08-28 10:18:03 +0800750 # Set write protect flag and reboot to take effect.
Tom Wai-Hong Tam05574ee2012-10-30 11:34:21 +0800751 self.ec.set_flash_write_protect(enable)
Vic Yang416f2032012-08-28 10:18:03 +0800752 self.sync_and_ec_reboot()
753 else:
754 # Reboot after deasserting hardware write protect pin to deactivate
755 # write protect. And then remove software write protect flag.
756 self.sync_and_ec_reboot()
Tom Wai-Hong Tam05574ee2012-10-30 11:34:21 +0800757 self.ec.set_flash_write_protect(enable)
Vic Yang2cabf812012-08-28 02:39:04 +0800758
759
Tom Wai-Hong Tam700c9fd2012-11-15 18:18:30 +0800760 def setup_ec_write_protect(self, ec_wp):
761 """Setup for EC write-protection.
762
763 It makes sure the EC in the requested write-protection state. If not, it
764 flips the state. Flipping the write-protection requires DUT reboot.
765
766 Args:
767 ec_wp: True to request EC write-protected; False to request EC not
768 write-protected; None to do nothing.
769 """
770 if ec_wp is None:
771 self._old_ec_wp = None
772 return
773 self._old_ec_wp = self.checkers.crossystem_checker({'wpsw_boot': '1'})
774 if ec_wp != self._old_ec_wp:
775 logging.info('The test required EC is %swrite-protected. Reboot '
776 'and flip the state.', '' if ec_wp else 'not ')
777 self.run_faft_step({
Tom Wai-Hong Tamdd830982013-01-16 10:31:05 +0800778 'reboot_action': (self.set_ec_write_protect_and_reboot, ec_wp),
779 'firmware_action': self.wait_dev_screen_and_ctrl_d,
Tom Wai-Hong Tam700c9fd2012-11-15 18:18:30 +0800780 })
781
782
783 def restore_ec_write_protect(self):
784 """Restore the original EC write-protection."""
785 if self._old_ec_wp is None:
786 return
787 if not self.checkers.crossystem_checker(
788 {'wpsw_boot': '1' if self._old_ec_wp else '0'}):
789 logging.info('Restore the original EC write protection and reboot.')
790 self.run_faft_step({
Tom Wai-Hong Tam44204b32012-11-20 13:55:40 +0800791 'reboot_action': (self.set_ec_write_protect_and_reboot,
Tom Wai-Hong Tamdd830982013-01-16 10:31:05 +0800792 self._old_ec_wp),
793 'firmware_action': self.wait_dev_screen_and_ctrl_d,
Tom Wai-Hong Tam700c9fd2012-11-15 18:18:30 +0800794 })
795
796
Tom Wai-Hong Tam91612bc2012-10-29 16:04:21 +0800797 def press_ctrl_d(self):
Tom Wai-Hong Tam1db43832011-12-09 10:50:56 +0800798 """Send Ctrl-D key to DUT."""
Tom Wai-Hong Tam9c15b4b2012-10-29 17:59:26 +0800799 if not self.client_attr.has_keyboard:
800 logging.info('Running usbkm232-ctrld...')
801 os.system('usbkm232-ctrld')
Tom Wai-Hong Tam1db43832011-12-09 10:50:56 +0800802 else:
803 self.servo.ctrl_d()
804
805
Tom Wai-Hong Tam91612bc2012-10-29 16:04:21 +0800806 def press_ctrl_u(self):
Tom Wai-Hong Tamadbec3e2012-10-15 14:20:15 +0800807 """Send Ctrl-U key to DUT.
808
809 Raises:
810 error.TestError: if a non-Chrome EC device or no Ctrl-U command given
811 on a no-build-in-keyboard device.
812 """
Tom Wai-Hong Tam9c15b4b2012-10-29 17:59:26 +0800813 if not self.client_attr.has_keyboard:
814 logging.info('Running usbkm232-ctrlu...')
815 os.system('usbkm232-ctrlu')
Tom Wai-Hong Tamadbec3e2012-10-15 14:20:15 +0800816 elif self.check_ec_capability(['keyboard'], suppress_warning=True):
817 self.ec.key_down('<ctrl_l>')
818 self.ec.key_down('u')
819 self.ec.key_up('u')
820 self.ec.key_up('<ctrl_l>')
821 elif self.client_attr.has_keyboard:
822 raise error.TestError(
823 "Can't send Ctrl-U to DUT without using Chrome EC.")
824 else:
825 raise error.TestError(
826 "Should specify the ctrl_u_cmd argument.")
827
828
Tom Wai-Hong Tam91612bc2012-10-29 16:04:21 +0800829 def press_enter(self):
Tom Wai-Hong Tam1db43832011-12-09 10:50:56 +0800830 """Send Enter key to DUT."""
Tom Wai-Hong Tam9c15b4b2012-10-29 17:59:26 +0800831 if not self.client_attr.has_keyboard:
832 logging.info('Running usbkm232-enter...')
833 os.system('usbkm232-enter')
Tom Wai-Hong Tam1db43832011-12-09 10:50:56 +0800834 else:
835 self.servo.enter_key()
836
837
Tom Wai-Hong Tam56977782012-11-23 16:13:28 +0800838 def wait_dev_screen_and_ctrl_d(self):
839 """Wait for firmware warning screen and press Ctrl-D."""
840 time.sleep(self.delay.dev_screen)
841 self.press_ctrl_d()
842
843
Tom Wai-Hong Tama9c1a502011-11-10 06:39:26 +0800844 def wait_fw_screen_and_ctrl_d(self):
845 """Wait for firmware warning screen and press Ctrl-D."""
Tom Wai-Hong Tam41738762012-10-29 14:32:39 +0800846 time.sleep(self.delay.firmware_screen)
Tom Wai-Hong Tam91612bc2012-10-29 16:04:21 +0800847 self.press_ctrl_d()
Tom Wai-Hong Tama9c1a502011-11-10 06:39:26 +0800848
849
Tom Wai-Hong Tamadbec3e2012-10-15 14:20:15 +0800850 def wait_fw_screen_and_ctrl_u(self):
851 """Wait for firmware warning screen and press Ctrl-U."""
Tom Wai-Hong Tam41738762012-10-29 14:32:39 +0800852 time.sleep(self.delay.firmware_screen)
Tom Wai-Hong Tam91612bc2012-10-29 16:04:21 +0800853 self.press_ctrl_u()
Tom Wai-Hong Tamadbec3e2012-10-15 14:20:15 +0800854
855
Tom Wai-Hong Tam78709592011-12-19 11:16:50 +0800856 def wait_fw_screen_and_trigger_recovery(self, need_dev_transition=False):
857 """Wait for firmware warning screen and trigger recovery boot."""
Tom Wai-Hong Tam41738762012-10-29 14:32:39 +0800858 time.sleep(self.delay.firmware_screen)
Tom Wai-Hong Tam91612bc2012-10-29 16:04:21 +0800859 self.press_enter()
Tom Wai-Hong Tam78709592011-12-19 11:16:50 +0800860
861 # For Alex/ZGB, there is a dev warning screen in text mode.
862 # Skip it by pressing Ctrl-D.
863 if need_dev_transition:
Tom Wai-Hong Tam41738762012-10-29 14:32:39 +0800864 time.sleep(self.delay.legacy_text_screen)
Tom Wai-Hong Tam91612bc2012-10-29 16:04:21 +0800865 self.press_ctrl_d()
Tom Wai-Hong Tam78709592011-12-19 11:16:50 +0800866
867
Mike Truty49153d82012-08-21 22:27:30 -0500868 def wait_fw_screen_and_unplug_usb(self):
869 """Wait for firmware warning screen and then unplug the servo USB."""
Tom Wai-Hong Tam41738762012-10-29 14:32:39 +0800870 time.sleep(self.delay.load_usb)
Vadim Bendeburye7bd9362012-12-19 14:35:20 -0800871 self.servo.switch_usbkey('host')
Tom Wai-Hong Tam41738762012-10-29 14:32:39 +0800872 time.sleep(self.delay.between_usb_plug)
Mike Truty49153d82012-08-21 22:27:30 -0500873
874
875 def wait_fw_screen_and_plug_usb(self):
876 """Wait for firmware warning screen and then unplug and plug the USB."""
877 self.wait_fw_screen_and_unplug_usb()
Vadim Bendeburye7bd9362012-12-19 14:35:20 -0800878 self.servo.switch_usbkey('dut')
Tom Wai-Hong Tam5d2f4702011-12-06 10:42:31 +0800879
880
Tom Wai-Hong Tam78709592011-12-19 11:16:50 +0800881 def wait_fw_screen_and_press_power(self):
882 """Wait for firmware warning screen and press power button."""
Tom Wai-Hong Tam41738762012-10-29 14:32:39 +0800883 time.sleep(self.delay.firmware_screen)
Tom Wai-Hong Tam7317c042012-08-14 11:59:06 +0800884 # While the firmware screen, the power button probing loop sleeps
885 # 0.25 second on every scan. Use the normal delay (1.2 second) for
886 # power press.
887 self.servo.power_normal_press()
Tom Wai-Hong Tam78709592011-12-19 11:16:50 +0800888
889
Tom Wai-Hong Tam4f5e5922012-07-27 16:23:15 +0800890 def wait_longer_fw_screen_and_press_power(self):
891 """Wait for firmware screen without timeout and press power button."""
Tom Wai-Hong Tam41738762012-10-29 14:32:39 +0800892 time.sleep(self.delay.dev_screen_timeout)
Tom Wai-Hong Tam4f5e5922012-07-27 16:23:15 +0800893 self.wait_fw_screen_and_press_power()
894
895
Tom Wai-Hong Tam78709592011-12-19 11:16:50 +0800896 def wait_fw_screen_and_close_lid(self):
897 """Wait for firmware warning screen and close lid."""
Tom Wai-Hong Tam41738762012-10-29 14:32:39 +0800898 time.sleep(self.delay.firmware_screen)
Tom Wai-Hong Tam78709592011-12-19 11:16:50 +0800899 self.servo.lid_close()
900
901
Tom Wai-Hong Tam473cfa72012-07-27 17:16:57 +0800902 def wait_longer_fw_screen_and_close_lid(self):
903 """Wait for firmware screen without timeout and close lid."""
Tom Wai-Hong Tam41738762012-10-29 14:32:39 +0800904 time.sleep(self.delay.firmware_screen)
Tom Wai-Hong Tam473cfa72012-07-27 17:16:57 +0800905 self.wait_fw_screen_and_close_lid()
906
907
Tom Wai-Hong Tam01d5e572012-10-23 10:07:11 +0800908 def setup_gbb_flags(self):
909 """Setup the GBB flags for FAFT test."""
910 if self.check_setup_done('gbb_flags'):
911 return
912
913 logging.info('Set proper GBB flags for test.')
914 self.clear_set_gbb_flags(vboot.GBB_FLAG_DEV_SCREEN_SHORT_DELAY |
915 vboot.GBB_FLAG_FORCE_DEV_SWITCH_ON |
916 vboot.GBB_FLAG_FORCE_DEV_BOOT_USB |
917 vboot.GBB_FLAG_DISABLE_FW_ROLLBACK_CHECK,
Gediminas Ramanauskasba352ad2012-11-09 09:43:32 -0800918 vboot.GBB_FLAG_ENTER_TRIGGERS_TONORM |
919 vboot.GBB_FLAG_FAFT_KEY_OVERIDE)
Tom Wai-Hong Tam01d5e572012-10-23 10:07:11 +0800920 self.mark_setup_done('gbb_flags')
921
922
Tom Wai-Hong Tamfd590c92011-11-25 11:50:57 +0800923 def setup_tried_fwb(self, tried_fwb):
924 """Setup for fw B tried state.
925
926 It makes sure the system in the requested fw B tried state. If not, it
927 tries to do so.
928
929 Args:
930 tried_fwb: True if requested in tried_fwb=1; False if tried_fwb=0.
931 """
932 if tried_fwb:
Vic Yangf93f7022012-10-31 09:40:36 +0800933 if not self.checkers.crossystem_checker({'tried_fwb': '1'}):
Tom Wai-Hong Tamfd590c92011-11-25 11:50:57 +0800934 logging.info(
935 'Firmware is not booted with tried_fwb. Reboot into it.')
936 self.run_faft_step({
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800937 'userspace_action': self.faft_client.system.set_try_fw_b,
Tom Wai-Hong Tamfd590c92011-11-25 11:50:57 +0800938 })
939 else:
Vic Yangf93f7022012-10-31 09:40:36 +0800940 if not self.checkers.crossystem_checker({'tried_fwb': '0'}):
Tom Wai-Hong Tamfd590c92011-11-25 11:50:57 +0800941 logging.info(
942 'Firmware is booted with tried_fwb. Reboot to clear.')
943 self.run_faft_step({})
944
945
Tom Wai-Hong Tama373f802012-07-31 21:16:48 +0800946 def enable_rec_mode_and_reboot(self):
947 """Switch to rec mode and reboot.
948
949 This method emulates the behavior of the old physical recovery switch,
950 i.e. switch ON + reboot + switch OFF, and the new keyboard controlled
951 recovery mode, i.e. just press Power + Esc + Refresh.
952 """
Tom Wai-Hong Tam80419a82012-10-30 09:10:00 +0800953 if self.client_attr.chrome_ec:
Tom Wai-Hong Tam41128082012-11-16 12:02:45 +0800954 # Reset twice to emulate a long recovery-key-combo hold.
955 cold_reset_num = 2 if self.client_attr.long_rec_combo else 1
Tom Wai-Hong Tam4c9684a2012-12-11 10:48:05 +0800956 for i in range(cold_reset_num):
957 if i:
958 time.sleep(self.delay.ec_boot_to_console)
Tom Wai-Hong Tam41128082012-11-16 12:02:45 +0800959 # Cold reset to clear EC_IN_RW signal
960 self.servo.set('cold_reset', 'on')
961 time.sleep(self.delay.hold_cold_reset)
962 self.servo.set('cold_reset', 'off')
Tom Wai-Hong Tambb92e6c2012-10-30 11:06:09 +0800963 self.ec.reboot("ap-off")
Tom Wai-Hong Tam41738762012-10-29 14:32:39 +0800964 time.sleep(self.delay.ec_boot_to_console)
Tom Wai-Hong Tam665281c2012-10-30 11:55:10 +0800965 self.ec.set_hostevent(chrome_ec.HOSTEVENT_KEYBOARD_RECOVERY)
Vic Yang611dd852012-08-02 15:36:31 +0800966 self.servo.power_short_press()
Gediminas Ramanauskasba352ad2012-11-09 09:43:32 -0800967 elif self.client_attr.broken_rec_mode:
Tom Wai-Hong Tamc5c14ef2012-11-20 16:33:37 +0800968 if self._host and self._host.has_power():
Gediminas Ramanauskasba352ad2012-11-09 09:43:32 -0800969 self._host.power_cycle()
970 else:
971 logging.info('You have %d seconds to power cycle this device.',
972 self.delay.user_power_cycle)
973 time.sleep(self.delay.user_power_cycle)
974 logging.info('Booting to recovery mode.')
975 self.servo.custom_recovery_mode()
Tom Wai-Hong Tamac943172012-08-01 10:38:39 +0800976 else:
977 self.servo.enable_recovery_mode()
978 self.cold_reboot()
Tom Wai-Hong Tamad4aaae2012-12-12 11:02:06 +0800979 time.sleep(self.delay.ec_boot_to_console)
Tom Wai-Hong Tamac943172012-08-01 10:38:39 +0800980 self.servo.disable_recovery_mode()
Tom Wai-Hong Tama373f802012-07-31 21:16:48 +0800981
982
Tom Wai-Hong Tam0b9e6d72012-07-31 20:54:06 +0800983 def enable_dev_mode_and_reboot(self):
984 """Switch to developer mode and reboot."""
Vic Yange7553162012-06-20 16:20:47 +0800985 if self.client_attr.keyboard_dev:
986 self.enable_keyboard_dev_mode()
987 else:
988 self.servo.enable_development_mode()
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800989 self.faft_client.system.run_shell_command(
Vic Yange7553162012-06-20 16:20:47 +0800990 'chromeos-firmwareupdate --mode todev && reboot')
Tom Wai-Hong Tam78709592011-12-19 11:16:50 +0800991
992
Tom Wai-Hong Tam0b9e6d72012-07-31 20:54:06 +0800993 def enable_normal_mode_and_reboot(self):
994 """Switch to normal mode and reboot."""
Vic Yange7553162012-06-20 16:20:47 +0800995 if self.client_attr.keyboard_dev:
996 self.disable_keyboard_dev_mode()
997 else:
998 self.servo.disable_development_mode()
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800999 self.faft_client.system.run_shell_command(
Vic Yange7553162012-06-20 16:20:47 +08001000 'chromeos-firmwareupdate --mode tonormal && reboot')
1001
1002
1003 def wait_fw_screen_and_switch_keyboard_dev_mode(self, dev):
1004 """Wait for firmware screen and then switch into or out of dev mode.
1005
1006 Args:
1007 dev: True if switching into dev mode. Otherwise, False.
1008 """
Tom Wai-Hong Tam41738762012-10-29 14:32:39 +08001009 time.sleep(self.delay.firmware_screen)
Vic Yange7553162012-06-20 16:20:47 +08001010 if dev:
Tom Wai-Hong Tam91612bc2012-10-29 16:04:21 +08001011 self.press_ctrl_d()
Vic Yange7553162012-06-20 16:20:47 +08001012 else:
Tom Wai-Hong Tam91612bc2012-10-29 16:04:21 +08001013 self.press_enter()
Vic Yang0dc84b82012-10-31 12:29:39 +08001014 time.sleep(self.delay.confirm_screen)
Tom Wai-Hong Tam91612bc2012-10-29 16:04:21 +08001015 self.press_enter()
Vic Yange7553162012-06-20 16:20:47 +08001016
1017
1018 def enable_keyboard_dev_mode(self):
1019 logging.info("Enabling keyboard controlled developer mode")
Tom Wai-Hong Tamf1a17d72012-07-26 11:39:52 +08001020 # Plug out USB disk for preventing recovery boot without warning
Vadim Bendeburye7bd9362012-12-19 14:35:20 -08001021 self.servo.switch_usbkey('host')
Vic Yange7553162012-06-20 16:20:47 +08001022 # Rebooting EC with rec mode on. Should power on AP.
Tom Wai-Hong Tama373f802012-07-31 21:16:48 +08001023 self.enable_rec_mode_and_reboot()
Tom Wai-Hong Tam8c54eb82012-08-01 10:31:07 +08001024 self.wait_for_client_offline()
Vic Yange7553162012-06-20 16:20:47 +08001025 self.wait_fw_screen_and_switch_keyboard_dev_mode(dev=True)
Vic Yange7553162012-06-20 16:20:47 +08001026
Gediminas Ramanauskas9da80f22012-11-14 12:59:43 -08001027 # TODO (crosbug.com/p/16231) remove this conditional completely if/when
1028 # issue is resolved.
1029 if self.client_attr.platform == 'Parrot':
1030 self.wait_for_client_offline()
1031 self.cold_reboot()
1032
Vic Yange7553162012-06-20 16:20:47 +08001033
1034 def disable_keyboard_dev_mode(self):
1035 logging.info("Disabling keyboard controlled developer mode")
Gediminas Ramanauskasba352ad2012-11-09 09:43:32 -08001036 if (not self.client_attr.chrome_ec and
1037 not self.client_attr.broken_rec_mode):
Vic Yang611dd852012-08-02 15:36:31 +08001038 self.servo.disable_recovery_mode()
Tom Wai-Hong Tam7ad99ab2012-07-30 19:30:51 +08001039 self.cold_reboot()
Tom Wai-Hong Tam8c54eb82012-08-01 10:31:07 +08001040 self.wait_for_client_offline()
Vic Yange7553162012-06-20 16:20:47 +08001041 self.wait_fw_screen_and_switch_keyboard_dev_mode(dev=False)
Tom Wai-Hong Tam78709592011-12-19 11:16:50 +08001042
1043
Tom Wai-Hong Tama9c1a502011-11-10 06:39:26 +08001044 def setup_dev_mode(self, dev_mode):
1045 """Setup for development mode.
1046
Tom Wai-Hong Tamfd590c92011-11-25 11:50:57 +08001047 It makes sure the system in the requested normal/dev mode. If not, it
Tom Wai-Hong Tama9c1a502011-11-10 06:39:26 +08001048 tries to do so.
1049
1050 Args:
1051 dev_mode: True if requested in dev mode; False if normal mode.
1052 """
Tom Wai-Hong Tamfd590c92011-11-25 11:50:57 +08001053 # Change the default firmware_action for dev mode passing the fw screen.
1054 self.register_faft_template({
Tom Wai-Hong Tam56977782012-11-23 16:13:28 +08001055 'firmware_action': (self.wait_dev_screen_and_ctrl_d if dev_mode
Tom Wai-Hong Tamfd590c92011-11-25 11:50:57 +08001056 else None),
1057 })
Tom Wai-Hong Tama9c1a502011-11-10 06:39:26 +08001058 if dev_mode:
Vic Yange7553162012-06-20 16:20:47 +08001059 if (not self.client_attr.keyboard_dev and
Vic Yangf93f7022012-10-31 09:40:36 +08001060 not self.checkers.crossystem_checker({'devsw_cur': '1'})):
Tom Wai-Hong Tama9c1a502011-11-10 06:39:26 +08001061 logging.info('Dev switch is not on. Now switch it on.')
1062 self.servo.enable_development_mode()
Vic Yangf93f7022012-10-31 09:40:36 +08001063 if not self.checkers.crossystem_checker({'devsw_boot': '1',
Tom Wai-Hong Tama9c1a502011-11-10 06:39:26 +08001064 'mainfw_type': 'developer'}):
1065 logging.info('System is not in dev mode. Reboot into it.')
Tom Wai-Hong Tamfd590c92011-11-25 11:50:57 +08001066 self.run_faft_step({
Vic Yange7553162012-06-20 16:20:47 +08001067 'userspace_action': None if self.client_attr.keyboard_dev
Chun-ting Changd43aa9b2012-11-16 10:12:05 +08001068 else (self.faft_client.system.run_shell_command,
Tom Wai-Hong Tamc7ecfca2011-12-06 11:12:31 +08001069 'chromeos-firmwareupdate --mode todev && reboot'),
Vic Yange7553162012-06-20 16:20:47 +08001070 'reboot_action': self.enable_keyboard_dev_mode if
1071 self.client_attr.keyboard_dev else None,
Tom Wai-Hong Tamfd590c92011-11-25 11:50:57 +08001072 })
Tom Wai-Hong Tama9c1a502011-11-10 06:39:26 +08001073 else:
Vic Yange7553162012-06-20 16:20:47 +08001074 if (not self.client_attr.keyboard_dev and
Vic Yangf93f7022012-10-31 09:40:36 +08001075 not self.checkers.crossystem_checker({'devsw_cur': '0'})):
Tom Wai-Hong Tama9c1a502011-11-10 06:39:26 +08001076 logging.info('Dev switch is not off. Now switch it off.')
1077 self.servo.disable_development_mode()
Vic Yangf93f7022012-10-31 09:40:36 +08001078 if not self.checkers.crossystem_checker({'devsw_boot': '0',
Tom Wai-Hong Tama9c1a502011-11-10 06:39:26 +08001079 'mainfw_type': 'normal'}):
1080 logging.info('System is not in normal mode. Reboot into it.')
Tom Wai-Hong Tamfd590c92011-11-25 11:50:57 +08001081 self.run_faft_step({
Vic Yange7553162012-06-20 16:20:47 +08001082 'userspace_action': None if self.client_attr.keyboard_dev
Chun-ting Changd43aa9b2012-11-16 10:12:05 +08001083 else (self.faft_client.system.run_shell_command,
Tom Wai-Hong Tamc7ecfca2011-12-06 11:12:31 +08001084 'chromeos-firmwareupdate --mode tonormal && reboot'),
Vic Yange7553162012-06-20 16:20:47 +08001085 'reboot_action': self.disable_keyboard_dev_mode if
1086 self.client_attr.keyboard_dev else None,
Tom Wai-Hong Tamfd590c92011-11-25 11:50:57 +08001087 })
Tom Wai-Hong Tama9c1a502011-11-10 06:39:26 +08001088
1089
Tom Wai-Hong Tam4c153fa2013-01-22 13:56:06 +08001090 def setup_rw_boot(self, section='a'):
1091 """Make sure firmware is in RW-boot mode.
1092
1093 If the given firmware section is in RO-boot mode, turn off the RO-boot
1094 flag and reboot DUT into RW-boot mode.
1095
1096 Args:
1097 section: A firmware section, either 'a' or 'b'.
1098 """
1099 flags = self.faft_client.bios.get_preamble_flags(section)
1100 if flags & vboot.PREAMBLE_USE_RO_NORMAL:
1101 flags = flags ^ vboot.PREAMBLE_USE_RO_NORMAL
1102 self.run_faft_step({
1103 'userspace_action': (self.faft_client.bios.set_preamble_flags,
1104 (section, flags))
1105 })
1106
1107
Tom Wai-Hong Tamcfda61f2011-11-02 17:41:01 +08001108 def setup_kernel(self, part):
1109 """Setup for kernel test.
1110
1111 It makes sure both kernel A and B bootable and the current boot is
1112 the requested kernel part.
1113
1114 Args:
Tom Wai-Hong Tama9c1a502011-11-10 06:39:26 +08001115 part: A string of kernel partition number or 'a'/'b'.
Tom Wai-Hong Tamcfda61f2011-11-02 17:41:01 +08001116 """
1117 self.ensure_kernel_boot(part)
Chun-ting Changd43aa9b2012-11-16 10:12:05 +08001118 if self.faft_client.kernel.diff_a_b():
Tom Wai-Hong Tam622d0ba2012-08-15 16:29:05 +08001119 self.copy_kernel_and_rootfs(from_part=part,
1120 to_part=self.OTHER_KERNEL_MAP[part])
Tom Wai-Hong Tamcfda61f2011-11-02 17:41:01 +08001121 self.reset_and_prioritize_kernel(part)
1122
1123
1124 def reset_and_prioritize_kernel(self, part):
1125 """Make the requested partition highest priority.
1126
1127 This function also reset kerenl A and B to bootable.
1128
1129 Args:
Tom Wai-Hong Tama9c1a502011-11-10 06:39:26 +08001130 part: A string of partition number to be prioritized.
Tom Wai-Hong Tamcfda61f2011-11-02 17:41:01 +08001131 """
Chun-ting Changd43aa9b2012-11-16 10:12:05 +08001132 root_dev = self.faft_client.system.get_root_dev()
Tom Wai-Hong Tamcfda61f2011-11-02 17:41:01 +08001133 # Reset kernel A and B to bootable.
Chun-ting Changd43aa9b2012-11-16 10:12:05 +08001134 self.faft_client.system.run_shell_command(
1135 'cgpt add -i%s -P1 -S1 -T0 %s' % (self.KERNEL_MAP['a'], root_dev))
1136 self.faft_client.system.run_shell_command(
1137 'cgpt add -i%s -P1 -S1 -T0 %s' % (self.KERNEL_MAP['b'], root_dev))
Tom Wai-Hong Tamcfda61f2011-11-02 17:41:01 +08001138 # Set kernel part highest priority.
Chun-ting Changd43aa9b2012-11-16 10:12:05 +08001139 self.faft_client.system.run_shell_command('cgpt prioritize -i%s %s' %
Tom Wai-Hong Tamcfda61f2011-11-02 17:41:01 +08001140 (self.KERNEL_MAP[part], root_dev))
Tom Wai-Hong Tam6a863ba2011-12-08 10:13:28 +08001141 # Safer to sync and wait until the cgpt status written to the disk.
Chun-ting Changd43aa9b2012-11-16 10:12:05 +08001142 self.faft_client.system.run_shell_command('sync')
Tom Wai-Hong Tam41738762012-10-29 14:32:39 +08001143 time.sleep(self.delay.sync)
Tom Wai-Hong Tamcfda61f2011-11-02 17:41:01 +08001144
1145
Tom Wai-Hong Tam7ad99ab2012-07-30 19:30:51 +08001146 def warm_reboot(self):
1147 """Request a warm reboot.
1148
Tom Wai-Hong Tamb06f0802012-07-31 16:27:50 +08001149 A wrapper for underlying servo warm reset.
Tom Wai-Hong Tam7ad99ab2012-07-30 19:30:51 +08001150 """
Tom Wai-Hong Tamb06f0802012-07-31 16:27:50 +08001151 # Use cold reset if the warm reset is broken.
1152 if self.client_attr.broken_warm_reset:
Gediminas Ramanauskase021e152012-09-04 19:10:59 -07001153 logging.info('broken_warm_reset is True. Cold rebooting instead.')
1154 self.cold_reboot()
Tom Wai-Hong Tamb06f0802012-07-31 16:27:50 +08001155 else:
1156 self.servo.warm_reset()
Tom Wai-Hong Tam7ad99ab2012-07-30 19:30:51 +08001157
1158
1159 def cold_reboot(self):
1160 """Request a cold reboot.
1161
1162 A wrapper for underlying servo cold reset.
1163 """
Gediminas Ramanauskasc6025692012-10-23 14:33:40 -07001164 if self.client_attr.broken_warm_reset:
Tom Wai-Hong Tama276d0a2012-08-22 11:15:17 +08001165 self.servo.set('pwr_button', 'press')
1166 self.servo.set('cold_reset', 'on')
1167 self.servo.set('cold_reset', 'off')
Tom Wai-Hong Tam41738762012-10-29 14:32:39 +08001168 time.sleep(self.delay.ec_boot_to_pwr_button)
Tom Wai-Hong Tama276d0a2012-08-22 11:15:17 +08001169 self.servo.set('pwr_button', 'release')
Tom Wai-Hong Tam7ad99ab2012-07-30 19:30:51 +08001170 else:
1171 self.servo.cold_reset()
1172
1173
Tom Wai-Hong Tamb21b6b42012-07-26 10:46:30 +08001174 def sync_and_warm_reboot(self):
Tom Wai-Hong Tamf1e34972011-11-02 17:07:04 +08001175 """Request the client sync and do a warm reboot.
1176
1177 This is the default reboot action on FAFT.
1178 """
Chun-ting Changd43aa9b2012-11-16 10:12:05 +08001179 self.faft_client.system.run_shell_command('sync')
Tom Wai-Hong Tam41738762012-10-29 14:32:39 +08001180 time.sleep(self.delay.sync)
Tom Wai-Hong Tam7ad99ab2012-07-30 19:30:51 +08001181 self.warm_reboot()
Tom Wai-Hong Tamf1e34972011-11-02 17:07:04 +08001182
1183
Tom Wai-Hong Tamb21b6b42012-07-26 10:46:30 +08001184 def sync_and_cold_reboot(self):
1185 """Request the client sync and do a cold reboot.
1186
1187 This reboot action is used to reset EC for recovery mode.
1188 """
Chun-ting Changd43aa9b2012-11-16 10:12:05 +08001189 self.faft_client.system.run_shell_command('sync')
Tom Wai-Hong Tam41738762012-10-29 14:32:39 +08001190 time.sleep(self.delay.sync)
Tom Wai-Hong Tam7ad99ab2012-07-30 19:30:51 +08001191 self.cold_reboot()
Tom Wai-Hong Tamb21b6b42012-07-26 10:46:30 +08001192
1193
Tom Wai-Hong Tambb92e6c2012-10-30 11:06:09 +08001194 def sync_and_ec_reboot(self, flags=''):
Vic Yangaeb10392012-08-28 09:25:09 +08001195 """Request the client sync and do a EC triggered reboot.
1196
1197 Args:
Tom Wai-Hong Tambb92e6c2012-10-30 11:06:09 +08001198 flags: Optional, a space-separated string of flags passed to EC
1199 reboot command, including:
1200 default: EC soft reboot;
1201 'hard': EC cold/hard reboot.
Vic Yangaeb10392012-08-28 09:25:09 +08001202 """
Chun-ting Changd43aa9b2012-11-16 10:12:05 +08001203 self.faft_client.system.run_shell_command('sync')
Tom Wai-Hong Tam41738762012-10-29 14:32:39 +08001204 time.sleep(self.delay.sync)
Tom Wai-Hong Tambb92e6c2012-10-30 11:06:09 +08001205 self.ec.reboot(flags)
Tom Wai-Hong Tamad4aaae2012-12-12 11:02:06 +08001206 time.sleep(self.delay.ec_boot_to_console)
Vic Yangf86728a2012-07-30 10:44:07 +08001207 self.check_lid_and_power_on()
1208
1209
Tom Wai-Hong Tam3d00ab72012-11-14 10:39:22 +08001210 def reboot_with_factory_install_shim(self):
1211 """Request reboot with factory install shim to reset TPM.
Chun-ting Changa4f65532012-10-17 16:57:28 +08001212
Tom Wai-Hong Tam3d00ab72012-11-14 10:39:22 +08001213 Factory install shim requires dev mode enabled. So this method switches
1214 firmware to dev mode first and reboot. The client uses factory install
1215 shim to reset TPM values.
Chun-ting Changa4f65532012-10-17 16:57:28 +08001216 """
Tom Wai-Hong Tam3d00ab72012-11-14 10:39:22 +08001217 # Unplug USB first to avoid the complicated USB autoboot cases.
Vadim Bendeburye7bd9362012-12-19 14:35:20 -08001218 self.servo.switch_usbkey('host')
Vic Yangf93f7022012-10-31 09:40:36 +08001219 is_dev = self.checkers.crossystem_checker({'devsw_boot': '1'})
Chun-ting Changa4f65532012-10-17 16:57:28 +08001220 if not is_dev:
1221 self.enable_dev_mode_and_reboot()
Vic Yangf1fdf712012-10-31 12:09:22 +08001222 time.sleep(self.delay.sync)
Chun-ting Changa4f65532012-10-17 16:57:28 +08001223 self.enable_rec_mode_and_reboot()
Tom Wai-Hong Tam3d00ab72012-11-14 10:39:22 +08001224 self.wait_fw_screen_and_plug_usb()
Tom Wai-Hong Tam41738762012-10-29 14:32:39 +08001225 time.sleep(self.delay.install_shim_done)
Chun-ting Changa4f65532012-10-17 16:57:28 +08001226 self.warm_reboot()
1227
1228
Tom Wai-Hong Tamc8f2ca02012-09-14 11:18:01 +08001229 def full_power_off_and_on(self):
1230 """Shutdown the device by pressing power button and power on again."""
1231 # Press power button to trigger Chrome OS normal shutdown process.
Tom Wai-Hong Tambe464992012-12-12 10:54:07 +08001232 # We use a customized delay since the normal-press 1.2s is not enough.
1233 self.servo.power_key(self.delay.hold_pwr_button)
Tom Wai-Hong Tam41738762012-10-29 14:32:39 +08001234 time.sleep(self.delay.shutdown)
Tom Wai-Hong Tamc8f2ca02012-09-14 11:18:01 +08001235 # Short press power button to boot DUT again.
1236 self.servo.power_short_press()
1237
1238
Vic Yangf86728a2012-07-30 10:44:07 +08001239 def check_lid_and_power_on(self):
1240 """
1241 On devices with EC software sync, system powers on after EC reboots if
1242 lid is open. Otherwise, the EC shuts down CPU after about 3 seconds.
1243 This method checks lid switch state and presses power button if
1244 necessary.
1245 """
1246 if self.servo.get("lid_open") == "no":
Tom Wai-Hong Tam41738762012-10-29 14:32:39 +08001247 time.sleep(self.delay.software_sync)
Vic Yangf86728a2012-07-30 10:44:07 +08001248 self.servo.power_short_press()
Vic Yang59cac9c2012-05-21 15:28:42 +08001249
1250
Tom Wai-Hong Tam78709592011-12-19 11:16:50 +08001251 def _modify_usb_kernel(self, usb_dev, from_magic, to_magic):
1252 """Modify the kernel header magic in USB stick.
1253
1254 The kernel header magic is the first 8-byte of kernel partition.
1255 We modify it to make it fail on kernel verification check.
1256
1257 Args:
1258 usb_dev: A string of USB stick path on the host, like '/dev/sdc'.
1259 from_magic: A string of magic which we change it from.
1260 to_magic: A string of magic which we change it to.
1261
1262 Raises:
1263 error.TestError: if failed to change magic.
1264 """
1265 assert len(from_magic) == 8
1266 assert len(to_magic) == 8
Tom Wai-Hong Tama1d9a0f2011-12-23 09:13:33 +08001267 # USB image only contains one kernel.
1268 kernel_part = self._join_part(usb_dev, self.KERNEL_MAP['a'])
Tom Wai-Hong Tam78709592011-12-19 11:16:50 +08001269 read_cmd = "sudo dd if=%s bs=8 count=1 2>/dev/null" % kernel_part
1270 current_magic = utils.system_output(read_cmd)
1271 if current_magic == to_magic:
Vic Yang772df8a2012-10-31 10:10:49 +08001272 logging.info("The kernel magic is already %s.", current_magic)
Tom Wai-Hong Tam78709592011-12-19 11:16:50 +08001273 return
1274 if current_magic != from_magic:
1275 raise error.TestError("Invalid kernel image on USB: wrong magic.")
1276
Vic Yang772df8a2012-10-31 10:10:49 +08001277 logging.info('Modify the kernel magic in USB, from %s to %s.',
1278 from_magic, to_magic)
Tom Wai-Hong Tam78709592011-12-19 11:16:50 +08001279 write_cmd = ("echo -n '%s' | sudo dd of=%s oflag=sync conv=notrunc "
1280 " 2>/dev/null" % (to_magic, kernel_part))
1281 utils.system(write_cmd)
1282
1283 if utils.system_output(read_cmd) != to_magic:
1284 raise error.TestError("Failed to write new magic.")
1285
1286
1287 def corrupt_usb_kernel(self, usb_dev):
1288 """Corrupt USB kernel by modifying its magic from CHROMEOS to CORRUPTD.
1289
1290 Args:
1291 usb_dev: A string of USB stick path on the host, like '/dev/sdc'.
1292 """
1293 self._modify_usb_kernel(usb_dev, self.CHROMEOS_MAGIC,
1294 self.CORRUPTED_MAGIC)
1295
1296
1297 def restore_usb_kernel(self, usb_dev):
1298 """Restore USB kernel by modifying its magic from CORRUPTD to CHROMEOS.
1299
1300 Args:
1301 usb_dev: A string of USB stick path on the host, like '/dev/sdc'.
1302 """
1303 self._modify_usb_kernel(usb_dev, self.CORRUPTED_MAGIC,
1304 self.CHROMEOS_MAGIC)
1305
1306
Tom Wai-Hong Tamfc700b52012-09-13 21:33:52 +08001307 def _call_action(self, action_tuple, check_status=False):
Tom Wai-Hong Tama70f0fe2011-09-02 18:28:47 +08001308 """Call the action function with/without arguments.
1309
1310 Args:
Tom Wai-Hong Tamfc700b52012-09-13 21:33:52 +08001311 action_tuple: A function, or a tuple (function, args, error_msg),
1312 in which, args and error_msg are optional. args is
1313 either a value or a tuple if multiple arguments.
Vic Yang52116d42012-11-05 16:22:34 +08001314 This can also be a list containing multiple function
1315 or tuple. In this case, these actions are called in
1316 sequence.
Tom Wai-Hong Tamfc700b52012-09-13 21:33:52 +08001317 check_status: Check the return value of action function. If not
1318 succeed, raises a TestFail exception.
Tom Wai-Hong Tama70f0fe2011-09-02 18:28:47 +08001319
1320 Returns:
1321 The result value of the action function.
Tom Wai-Hong Tamfc700b52012-09-13 21:33:52 +08001322
1323 Raises:
1324 error.TestError: An error when the action function is not callable.
1325 error.TestFail: When check_status=True, action function not succeed.
Tom Wai-Hong Tama70f0fe2011-09-02 18:28:47 +08001326 """
Vic Yang52116d42012-11-05 16:22:34 +08001327 if isinstance(action_tuple, list):
1328 return all([self._call_action(action, check_status=check_status)
1329 for action in action_tuple])
1330
Tom Wai-Hong Tamfc700b52012-09-13 21:33:52 +08001331 action = action_tuple
1332 args = ()
1333 error_msg = 'Not succeed'
Tom Wai-Hong Tama70f0fe2011-09-02 18:28:47 +08001334 if isinstance(action_tuple, tuple):
1335 action = action_tuple[0]
Tom Wai-Hong Tamfc700b52012-09-13 21:33:52 +08001336 if len(action_tuple) >= 2:
1337 args = action_tuple[1]
1338 if not isinstance(args, tuple):
1339 args = (args,)
1340 if len(action_tuple) >= 3:
Tom Wai-Hong Tamff560882012-10-15 16:50:06 +08001341 error_msg = action_tuple[2]
Tom Wai-Hong Tama70f0fe2011-09-02 18:28:47 +08001342
Tom Wai-Hong Tamfc700b52012-09-13 21:33:52 +08001343 if action is None:
1344 return
1345
1346 if not callable(action):
1347 raise error.TestError('action is not callable!')
1348
1349 info_msg = 'calling %s' % str(action)
1350 if args:
1351 info_msg += ' with args %s' % str(args)
1352 logging.info(info_msg)
1353 ret = action(*args)
1354
1355 if check_status and not ret:
1356 raise error.TestFail('%s: %s returning %s' %
1357 (error_msg, info_msg, str(ret)))
1358 return ret
Tom Wai-Hong Tama70f0fe2011-09-02 18:28:47 +08001359
1360
Tom Wai-Hong Tam78709592011-12-19 11:16:50 +08001361 def run_shutdown_process(self, shutdown_action, pre_power_action=None,
Tom Wai-Hong Tam8da40de2012-12-12 12:15:54 +08001362 post_power_action=None, shutdown_timeout=None):
Tom Wai-Hong Tam78709592011-12-19 11:16:50 +08001363 """Run shutdown_action(), which makes DUT shutdown, and power it on.
1364
1365 Args:
1366 shutdown_action: a function which makes DUT shutdown, like pressing
1367 power key.
1368 pre_power_action: a function which is called before next power on.
1369 post_power_action: a function which is called after next power on.
Tom Wai-Hong Tam8da40de2012-12-12 12:15:54 +08001370 shutdown_timeout: a timeout to confirm DUT shutdown.
Tom Wai-Hong Tam78709592011-12-19 11:16:50 +08001371
1372 Raises:
1373 error.TestFail: if the shutdown_action() failed to turn DUT off.
1374 """
1375 self._call_action(shutdown_action)
1376 logging.info('Wait to ensure DUT shut down...')
1377 try:
Tom Wai-Hong Tam8da40de2012-12-12 12:15:54 +08001378 if shutdown_timeout is None:
1379 shutdown_timeout = self.delay.shutdown_timeout
1380 self.wait_for_client(timeout=shutdown_timeout)
Tom Wai-Hong Tam78709592011-12-19 11:16:50 +08001381 raise error.TestFail(
1382 'Should shut the device down after calling %s.' %
1383 str(shutdown_action))
1384 except AssertionError:
1385 logging.info(
1386 'DUT is surely shutdown. We are going to power it on again...')
1387
1388 if pre_power_action:
1389 self._call_action(pre_power_action)
Tom Wai-Hong Tam610262a2012-01-12 14:16:53 +08001390 self.servo.power_short_press()
Tom Wai-Hong Tam78709592011-12-19 11:16:50 +08001391 if post_power_action:
1392 self._call_action(post_power_action)
1393
1394
Tom Wai-Hong Tama70f0fe2011-09-02 18:28:47 +08001395 def register_faft_template(self, template):
1396 """Register FAFT template, the default FAFT_STEP of each step.
1397
Tom Wai-Hong Tam109f63c2011-12-08 14:58:27 +08001398 Any missing field falls back to the original faft_template.
1399
Tom Wai-Hong Tama70f0fe2011-09-02 18:28:47 +08001400 Args:
1401 template: A FAFT_STEP dict.
1402 """
Tom Wai-Hong Tam109f63c2011-12-08 14:58:27 +08001403 self._faft_template.update(template)
Tom Wai-Hong Tama70f0fe2011-09-02 18:28:47 +08001404
1405
1406 def register_faft_sequence(self, sequence):
1407 """Register FAFT sequence.
1408
1409 Args:
1410 sequence: A FAFT_SEQUENCE array which consisted of FAFT_STEP dicts.
1411 """
1412 self._faft_sequence = sequence
1413
1414
Tom Wai-Hong Tamc285f4c2012-10-30 15:44:39 +08001415 def run_faft_step(self, step, no_reboot=False, next_step=None):
Tom Wai-Hong Tam2c50dff2011-11-11 07:01:01 +08001416 """Run a single FAFT step.
1417
1418 Any missing field falls back to faft_template. An empty step means
1419 running the default faft_template.
1420
1421 Args:
1422 step: A FAFT_STEP dict.
1423 no_reboot: True to prevent running reboot_action and firmware_action.
Tom Wai-Hong Tamc285f4c2012-10-30 15:44:39 +08001424 next_step: Optional, a FAFT_STEP dict of the next step, which is used
1425 for diagnostic.
Tom Wai-Hong Tama70f0fe2011-09-02 18:28:47 +08001426
1427 Raises:
Tom Wai-Hong Tamd8445dc2011-12-15 09:00:04 +08001428 error.TestError: An error when the given step is not valid.
Tom Wai-Hong Tam4bb85e22012-10-25 14:35:24 +08001429 error.TestFail: Test failed in waiting DUT reboot.
Tom Wai-Hong Tama70f0fe2011-09-02 18:28:47 +08001430 """
Tom Wai-Hong Tamd8445dc2011-12-15 09:00:04 +08001431 FAFT_STEP_KEYS = ('state_checker', 'userspace_action', 'reboot_action',
1432 'firmware_action', 'install_deps_after_boot')
1433
Tom Wai-Hong Tam2c50dff2011-11-11 07:01:01 +08001434 test = {}
1435 test.update(self._faft_template)
1436 test.update(step)
1437
Tom Wai-Hong Tamd8445dc2011-12-15 09:00:04 +08001438 for key in test:
1439 if key not in FAFT_STEP_KEYS:
Tom Wai-Hong Tam78709592011-12-19 11:16:50 +08001440 raise error.TestError('Invalid key in FAFT step: %s', key)
Tom Wai-Hong Tamd8445dc2011-12-15 09:00:04 +08001441
Tom Wai-Hong Tam2c50dff2011-11-11 07:01:01 +08001442 if test['state_checker']:
Tom Wai-Hong Tamfc700b52012-09-13 21:33:52 +08001443 self._call_action(test['state_checker'], check_status=True)
Tom Wai-Hong Tam2c50dff2011-11-11 07:01:01 +08001444
1445 self._call_action(test['userspace_action'])
1446
1447 # Don't run reboot_action and firmware_action if no_reboot is True.
1448 if not no_reboot:
1449 self._call_action(test['reboot_action'])
1450 self.wait_for_client_offline()
1451 self._call_action(test['firmware_action'])
1452
Vic Yang8eaf5ad2012-09-13 14:05:37 +08001453 try:
1454 if 'install_deps_after_boot' in test:
1455 self.wait_for_client(
1456 install_deps=test['install_deps_after_boot'])
1457 else:
1458 self.wait_for_client()
1459 except AssertionError:
Yusuf Mohsinally928f8c72012-12-11 15:27:02 -08001460 logging.error('wait_for_client() timed out.')
Tom Wai-Hong Tamc285f4c2012-10-30 15:44:39 +08001461 self._restore_routine_from_timeout(next_step)
Tom Wai-Hong Tam2c50dff2011-11-11 07:01:01 +08001462
1463
1464 def run_faft_sequence(self):
1465 """Run FAFT sequence which was previously registered."""
Tom Wai-Hong Tama70f0fe2011-09-02 18:28:47 +08001466 sequence = self._faft_sequence
Tom Wai-Hong Tamc285f4c2012-10-30 15:44:39 +08001467 for index, step in enumerate(sequence):
Vic Yang772df8a2012-10-31 10:10:49 +08001468 logging.info('======== Running FAFT sequence step %d ========',
Tom Wai-Hong Tamc285f4c2012-10-30 15:44:39 +08001469 index + 1)
Tom Wai-Hong Tam2c50dff2011-11-11 07:01:01 +08001470 # Don't reboot in the last step.
Tom Wai-Hong Tamc285f4c2012-10-30 15:44:39 +08001471 if index == len(sequence) - 1:
1472 self.run_faft_step(step, no_reboot=True)
1473 else:
1474 self.run_faft_step(step, next_step=sequence[index + 1])
ctchang38ae4922012-09-03 17:01:16 +08001475
1476
ctchang38ae4922012-09-03 17:01:16 +08001477 def get_current_firmware_sha(self):
1478 """Get current firmware sha of body and vblock.
1479
1480 Returns:
1481 Current firmware sha follows the order (
1482 vblock_a_sha, body_a_sha, vblock_b_sha, body_b_sha)
1483 """
Chun-ting Changd43aa9b2012-11-16 10:12:05 +08001484 current_firmware_sha = (self.faft_client.bios.get_sig_sha('a'),
1485 self.faft_client.bios.get_body_sha('a'),
1486 self.faft_client.bios.get_sig_sha('b'),
1487 self.faft_client.bios.get_body_sha('b'))
ctchang38ae4922012-09-03 17:01:16 +08001488 return current_firmware_sha
1489
1490
Tom Wai-Hong Tame6232342012-09-24 16:18:01 +08001491 def is_firmware_changed(self):
1492 """Check if the current firmware changed, by comparing its SHA.
ctchang38ae4922012-09-03 17:01:16 +08001493
1494 Returns:
Tom Wai-Hong Tame6232342012-09-24 16:18:01 +08001495 True if it is changed, otherwise Flase.
ctchang38ae4922012-09-03 17:01:16 +08001496 """
Tom Wai-Hong Tame6232342012-09-24 16:18:01 +08001497 # Device may not be rebooted after test.
Chun-ting Changd43aa9b2012-11-16 10:12:05 +08001498 self.faft_client.bios.reload()
ctchang38ae4922012-09-03 17:01:16 +08001499
1500 current_sha = self.get_current_firmware_sha()
1501
1502 if current_sha == self._backup_firmware_sha:
Tom Wai-Hong Tame6232342012-09-24 16:18:01 +08001503 return False
ctchang38ae4922012-09-03 17:01:16 +08001504 else:
ctchang38ae4922012-09-03 17:01:16 +08001505 corrupt_VBOOTA = (current_sha[0] != self._backup_firmware_sha[0])
1506 corrupt_FVMAIN = (current_sha[1] != self._backup_firmware_sha[1])
1507 corrupt_VBOOTB = (current_sha[2] != self._backup_firmware_sha[2])
1508 corrupt_FVMAINB = (current_sha[3] != self._backup_firmware_sha[3])
Tom Wai-Hong Tame6232342012-09-24 16:18:01 +08001509 logging.info("Firmware changed:")
Vic Yang772df8a2012-10-31 10:10:49 +08001510 logging.info('VBOOTA is changed: %s', corrupt_VBOOTA)
1511 logging.info('VBOOTB is changed: %s', corrupt_VBOOTB)
1512 logging.info('FVMAIN is changed: %s', corrupt_FVMAIN)
1513 logging.info('FVMAINB is changed: %s', corrupt_FVMAINB)
Tom Wai-Hong Tame6232342012-09-24 16:18:01 +08001514 return True
ctchang38ae4922012-09-03 17:01:16 +08001515
1516
1517 def backup_firmware(self, suffix='.original'):
1518 """Backup firmware to file, and then send it to host.
1519
1520 Args:
1521 suffix: a string appended to backup file name
1522 """
Chun-ting Changd43aa9b2012-11-16 10:12:05 +08001523 remote_temp_dir = self.faft_client.system.create_temp_dir()
1524 self.faft_client.bios.dump_whole(os.path.join(remote_temp_dir, 'bios'))
Chun-ting Chang9380c2c2012-10-05 17:31:05 +08001525 self._client.get_file(os.path.join(remote_temp_dir, 'bios'),
1526 os.path.join(self.resultsdir, 'bios' + suffix))
ctchang38ae4922012-09-03 17:01:16 +08001527
1528 self._backup_firmware_sha = self.get_current_firmware_sha()
Vic Yang772df8a2012-10-31 10:10:49 +08001529 logging.info('Backup firmware stored in %s with suffix %s',
1530 self.resultsdir, suffix)
ctchang38ae4922012-09-03 17:01:16 +08001531
1532
Tom Wai-Hong Tame6232342012-09-24 16:18:01 +08001533 def is_firmware_saved(self):
1534 """Check if a firmware saved (called backup_firmware before).
1535
1536 Returns:
1537 True if the firmware is backuped; otherwise False.
1538 """
1539 return self._backup_firmware_sha != ()
1540
1541
Tom Wai-Hong Tam1dd11592012-10-26 15:01:45 +08001542 def clear_saved_firmware(self):
1543 """Clear the firmware saved by the method backup_firmware."""
1544 self._backup_firmware_sha = ()
1545
1546
ctchang38ae4922012-09-03 17:01:16 +08001547 def restore_firmware(self, suffix='.original'):
1548 """Restore firmware from host in resultsdir.
1549
1550 Args:
1551 suffix: a string appended to backup file name
1552 """
Tom Wai-Hong Tame6232342012-09-24 16:18:01 +08001553 if not self.is_firmware_changed():
ctchang38ae4922012-09-03 17:01:16 +08001554 return
1555
1556 # Backup current corrupted firmware.
1557 self.backup_firmware(suffix='.corrupt')
1558
1559 # Restore firmware.
Chun-ting Changd43aa9b2012-11-16 10:12:05 +08001560 remote_temp_dir = self.faft_client.system.create_temp_dir()
Chun-ting Chang9380c2c2012-10-05 17:31:05 +08001561 self._client.send_file(os.path.join(self.resultsdir, 'bios' + suffix),
1562 os.path.join(remote_temp_dir, 'bios'))
ctchang38ae4922012-09-03 17:01:16 +08001563
Chun-ting Changd43aa9b2012-11-16 10:12:05 +08001564 self.faft_client.bios.write_whole(
1565 os.path.join(remote_temp_dir, 'bios'))
Tom Wai-Hong Tame6232342012-09-24 16:18:01 +08001566 self.sync_and_warm_reboot()
1567 self.wait_for_client_offline()
Tom Wai-Hong Tame2f9cf92012-11-26 10:04:11 +08001568 self.wait_dev_screen_and_ctrl_d()
Tom Wai-Hong Tame6232342012-09-24 16:18:01 +08001569 self.wait_for_client()
1570
ctchang38ae4922012-09-03 17:01:16 +08001571 logging.info('Successfully restore firmware.')
Chun-ting Changf91ee0f2012-09-17 18:31:54 +08001572
1573
1574 def setup_firmwareupdate_shellball(self, shellball=None):
1575 """Deside a shellball to use in firmware update test.
1576
1577 Check if there is a given shellball, and it is a shell script. Then,
1578 send it to the remote host. Otherwise, use
1579 /usr/sbin/chromeos-firmwareupdate.
1580
1581 Args:
1582 shellball: path of a shellball or default to None.
1583
1584 Returns:
1585 Path of shellball in remote host.
1586 If use default shellball, reutrn None.
1587 """
1588 updater_path = None
1589 if shellball:
1590 # Determine the firmware file is a shellball or a raw binary.
1591 is_shellball = (utils.system_output("file %s" % shellball).find(
1592 "shell script") != -1)
1593 if is_shellball:
Vic Yang772df8a2012-10-31 10:10:49 +08001594 logging.info('Device will update firmware with shellball %s',
1595 shellball)
Chun-ting Changd43aa9b2012-11-16 10:12:05 +08001596 temp_dir = self.faft_client.system.create_temp_dir(
1597 'shellball_')
Chun-ting Changf91ee0f2012-09-17 18:31:54 +08001598 temp_shellball = os.path.join(temp_dir, 'updater.sh')
1599 self._client.send_file(shellball, temp_shellball)
1600 updater_path = temp_shellball
1601 else:
1602 raise error.TestFail(
1603 'The given shellball is not a shell script.')
1604 return updater_path