blob: df529e94a13cc702362f8e9e0b995eceea7ebd21 [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()
187 if not self._remote_infos['faft']['used']:
188 raise error.TestError('The use_faft flag should be enabled.')
189 self.register_faft_template({
190 'state_checker': (None),
191 'userspace_action': (None),
Tom Wai-Hong Tamb21b6b42012-07-26 10:46:30 +0800192 'reboot_action': (self.sync_and_warm_reboot),
Tom Wai-Hong Tama70f0fe2011-09-02 18:28:47 +0800193 'firmware_action': (None)
194 })
Tom Wai-Hong Tam19ad9682012-10-24 09:33:42 +0800195 self.install_test_image(self._install_image_path, self._firmware_update)
Tom Wai-Hong Tamb92669c2012-11-29 13:57:11 +0800196 self.record_system_info()
Tom Wai-Hong Tam01d5e572012-10-23 10:07:11 +0800197 self.setup_gbb_flags()
Tom Wai-Hong Tam700c9fd2012-11-15 18:18:30 +0800198 self.setup_ec_write_protect(ec_wp)
Tom Wai-Hong Tama70f0fe2011-09-02 18:28:47 +0800199
200
201 def cleanup(self):
202 """Autotest cleanup function."""
Tom Wai-Hong Tam700c9fd2012-11-15 18:18:30 +0800203 self.restore_ec_write_protect()
Tom Wai-Hong Tama70f0fe2011-09-02 18:28:47 +0800204 self._faft_sequence = ()
Tom Wai-Hong Tam109f63c2011-12-08 14:58:27 +0800205 self._faft_template = {}
Tom Wai-Hong Tama70f0fe2011-09-02 18:28:47 +0800206 super(FAFTSequence, self).cleanup()
207
208
Tom Wai-Hong Tamb92669c2012-11-29 13:57:11 +0800209 def record_system_info(self):
210 """Record some critical system info to the attr keyval.
211
212 This info is used by generate_test_report and local_dash later.
213 """
214 self.write_attr_keyval({
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800215 'fw_version': self.faft_client.ec.get_version(),
216 'hwid': self.faft_client.system.get_crossystem_value('hwid'),
217 'fwid': self.faft_client.system.get_crossystem_value('fwid'),
Tom Wai-Hong Tamb92669c2012-11-29 13:57:11 +0800218 })
219
220
Tom Wai-Hong Tam01d5e572012-10-23 10:07:11 +0800221 def invalidate_firmware_setup(self):
222 """Invalidate all firmware related setup state.
Vic Yangdbaba8f2012-10-17 16:05:35 +0800223
Tom Wai-Hong Tam01d5e572012-10-23 10:07:11 +0800224 This method is called when the firmware is re-flashed. It resets all
225 firmware related setup states so that the next test setup properly
226 again.
Vic Yangdbaba8f2012-10-17 16:05:35 +0800227 """
Tom Wai-Hong Tam01d5e572012-10-23 10:07:11 +0800228 self.unmark_setup_done('gbb_flags')
Vic Yangdbaba8f2012-10-17 16:05:35 +0800229
230
Tom Wai-Hong Tamc285f4c2012-10-30 15:44:39 +0800231 def _retrieve_recovery_reason_from_trap(self):
232 """Try to retrieve the recovery reason from a trapped recovery screen.
Tom Wai-Hong Tame6232342012-09-24 16:18:01 +0800233
Tom Wai-Hong Tamc285f4c2012-10-30 15:44:39 +0800234 Returns:
235 The recovery_reason, 0 if any error.
Tom Wai-Hong Tame6232342012-09-24 16:18:01 +0800236 """
Tom Wai-Hong Tamc285f4c2012-10-30 15:44:39 +0800237 recovery_reason = 0
Tom Wai-Hong Tam4bb85e22012-10-25 14:35:24 +0800238 logging.info('Try to retrieve recovery reason...')
Vadim Bendeburye7bd9362012-12-19 14:35:20 -0800239 if self.servo.get_usbkey_direction() == 'dut':
Tom Wai-Hong Tam4bb85e22012-10-25 14:35:24 +0800240 self.wait_fw_screen_and_plug_usb()
241 else:
Vadim Bendeburye7bd9362012-12-19 14:35:20 -0800242 self.servo.switch_usbkey('dut')
Tom Wai-Hong Tam4bb85e22012-10-25 14:35:24 +0800243
244 try:
245 self.wait_for_client(install_deps=True)
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800246 lines = self.faft_client.system.run_shell_command_get_output(
Tom Wai-Hong Tam4bb85e22012-10-25 14:35:24 +0800247 'crossystem recovery_reason')
Tom Wai-Hong Tamc285f4c2012-10-30 15:44:39 +0800248 recovery_reason = int(lines[0])
249 logging.info('Got the recovery reason %d.', recovery_reason)
Tom Wai-Hong Tam4bb85e22012-10-25 14:35:24 +0800250 except AssertionError:
251 logging.info('Failed to get the recovery reason.')
Tom Wai-Hong Tamc285f4c2012-10-30 15:44:39 +0800252 return recovery_reason
Tom Wai-Hong Tam4bb85e22012-10-25 14:35:24 +0800253
Tom Wai-Hong Tamc285f4c2012-10-30 15:44:39 +0800254
255 def _reset_client(self):
256 """Reset client to a workable state.
257
258 This method is called when the client is not responsive. It may be
259 caused by the following cases:
260 - halt on a firmware screen without timeout, e.g. REC_INSERT screen;
261 - corrupted firmware;
262 - corrutped OS image.
263 """
Tom Wai-Hong Tame6232342012-09-24 16:18:01 +0800264 # DUT may halt on a firmware screen. Try cold reboot.
265 logging.info('Try cold reboot...')
266 self.cold_reboot()
Tom Wai-Hong Tame2f9cf92012-11-26 10:04:11 +0800267 self.wait_for_client_offline()
268 self.wait_dev_screen_and_ctrl_d()
Tom Wai-Hong Tame6232342012-09-24 16:18:01 +0800269 try:
Vic Yang8eaf5ad2012-09-13 14:05:37 +0800270 self.wait_for_client()
Tom Wai-Hong Tame6232342012-09-24 16:18:01 +0800271 return
272 except AssertionError:
273 pass
274
275 # DUT may be broken by a corrupted firmware. Restore firmware.
276 # We assume the recovery boot still works fine. Since the recovery
277 # code is in RO region and all FAFT tests don't change the RO region
278 # except GBB.
279 if self.is_firmware_saved():
Tom Wai-Hong Tamc285f4c2012-10-30 15:44:39 +0800280 self._ensure_client_in_recovery()
Tom Wai-Hong Tame6232342012-09-24 16:18:01 +0800281 logging.info('Try restore the original firmware...')
282 if self.is_firmware_changed():
283 try:
284 self.restore_firmware()
285 return
286 except AssertionError:
287 logging.info('Restoring firmware doesn\'t help.')
288
289 # DUT may be broken by a corrupted OS image. Restore OS image.
Tom Wai-Hong Tamc285f4c2012-10-30 15:44:39 +0800290 self._ensure_client_in_recovery()
Tom Wai-Hong Tame6232342012-09-24 16:18:01 +0800291 logging.info('Try restore the OS image...')
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800292 self.faft_client.system.run_shell_command('chromeos-install --yes')
Tom Wai-Hong Tame6232342012-09-24 16:18:01 +0800293 self.sync_and_warm_reboot()
294 self.wait_for_client_offline()
Tom Wai-Hong Tame2f9cf92012-11-26 10:04:11 +0800295 self.wait_dev_screen_and_ctrl_d()
Tom Wai-Hong Tame6232342012-09-24 16:18:01 +0800296 try:
297 self.wait_for_client(install_deps=True)
298 logging.info('Successfully restore OS image.')
299 return
300 except AssertionError:
301 logging.info('Restoring OS image doesn\'t help.')
302
303
Tom Wai-Hong Tamc285f4c2012-10-30 15:44:39 +0800304 def _ensure_client_in_recovery(self):
Tom Wai-Hong Tame6232342012-09-24 16:18:01 +0800305 """Ensure client in recovery boot; reboot into it if necessary.
306
307 Raises:
308 error.TestError: if failed to boot the USB image.
309 """
310 # DUT works fine and is already in recovery boot, done.
311 if self._ping_test(self._client.ip, timeout=5):
Vic Yangf93f7022012-10-31 09:40:36 +0800312 if self.checkers.crossystem_checker({'mainfw_type': 'recovery'}):
Tom Wai-Hong Tame6232342012-09-24 16:18:01 +0800313 return
314
315 logging.info('Try boot into USB image...')
Vadim Bendeburye7bd9362012-12-19 14:35:20 -0800316 self.servo.switch_usbkey('host')
Tom Wai-Hong Tame6232342012-09-24 16:18:01 +0800317 self.enable_rec_mode_and_reboot()
318 self.wait_fw_screen_and_plug_usb()
319 try:
320 self.wait_for_client(install_deps=True)
321 except AssertionError:
322 raise error.TestError('Failed to boot the USB image.')
Vic Yang8eaf5ad2012-09-13 14:05:37 +0800323
324
Tom Wai-Hong Tamc285f4c2012-10-30 15:44:39 +0800325 def _restore_routine_from_timeout(self, next_step=None):
326 """A routine to try to restore the system from a timeout error.
327
328 This method is called when FAFT failed to connect DUT after reboot.
329
330 Args:
331 next_step: Optional, a FAFT_STEP dict of the next step, which is used
332 for diagnostic.
333
334 Raises:
335 error.TestFail: This exception is already raised, with a decription
336 why it failed.
337 """
338 next_checker_matched = False
339 if next_step is not None:
340 next_test = {}
341 next_test.update(self._faft_template)
342 next_test.update(next_step)
343
344 # TODO(waihong@chromium.org): Implement replugging the Ethernet to
345 # identify if it is a network flaky.
346
347 recovery_reason = self._retrieve_recovery_reason_from_trap()
348 if next_step is not None and recovery_reason:
349 if self._call_action(next_test['state_checker']):
350 # Repluging the USB can pass the state_checker of the next step,
351 # meaning that the firmware failed to boot into USB directly.
352 next_checker_matched = True
353
354 # Reset client to a workable state.
355 self._reset_client()
356
357 # Raise the proper TestFail exception.
358 if next_checker_matched:
359 raise error.TestFail('Firmware failed to auto-boot USB in the '
Tom Wai-Hong Tam66648432012-11-07 10:06:00 +0800360 'recovery boot (reason: %d)' % recovery_reason)
Tom Wai-Hong Tamc285f4c2012-10-30 15:44:39 +0800361 elif recovery_reason:
Tom Wai-Hong Tam66648432012-11-07 10:06:00 +0800362 raise error.TestFail('Trapped in the recovery screen (reason: %d) '
363 'and timed out' % recovery_reason)
Tom Wai-Hong Tamc285f4c2012-10-30 15:44:39 +0800364 else:
Tom Wai-Hong Tam66648432012-11-07 10:06:00 +0800365 raise error.TestFail('Timed out waiting for DUT reboot')
Tom Wai-Hong Tamc285f4c2012-10-30 15:44:39 +0800366
367
Tom Wai-Hong Tama6b382c2012-11-14 09:31:02 +0800368 def assert_test_image_in_usb_disk(self, usb_dev=None, install_shim=False):
Tom Wai-Hong Tam76c75072011-10-25 18:00:12 +0800369 """Assert an USB disk plugged-in on servo and a test image inside.
370
Tom Wai-Hong Tam91f49822011-12-28 15:44:15 +0800371 Args:
372 usb_dev: A string of USB stick path on the host, like '/dev/sdc'.
373 If None, it is detected automatically.
Tom Wai-Hong Tama6b382c2012-11-14 09:31:02 +0800374 install_shim: True to verify an install shim instead of a test image.
Tom Wai-Hong Tam91f49822011-12-28 15:44:15 +0800375
Tom Wai-Hong Tam76c75072011-10-25 18:00:12 +0800376 Raises:
Tom Wai-Hong Tama6b382c2012-11-14 09:31:02 +0800377 error.TestError: if USB disk not detected or not a test (install shim)
378 image.
Tom Wai-Hong Tam76c75072011-10-25 18:00:12 +0800379 """
Tom Wai-Hong Tam01d5e572012-10-23 10:07:11 +0800380 if self.check_setup_done('usb_check'):
Vic Yang54f70572012-10-19 17:05:26 +0800381 return
Tom Wai-Hong Tam91f49822011-12-28 15:44:15 +0800382 if usb_dev:
Vadim Bendeburye7bd9362012-12-19 14:35:20 -0800383 assert self.servo.get_usbkey_direction() == 'host'
Tom Wai-Hong Tam91f49822011-12-28 15:44:15 +0800384 else:
Vadim Bendeburye7bd9362012-12-19 14:35:20 -0800385 self.servo.switch_usbkey('host')
Tom Wai-Hong Tam91f49822011-12-28 15:44:15 +0800386 usb_dev = self.servo.probe_host_usb_dev()
387 if not usb_dev:
388 raise error.TestError(
389 'An USB disk should be plugged in the servo board.')
Vadim Bendebury89ec24e2012-12-17 12:54:18 -0800390
391 rootfs = '%s%s' % (usb_dev, self._ROOTFS_PARTITION_NUMBER)
392 logging.info('usb dev is %s', usb_dev)
393 tmpd = self.servo.system_output('mktemp -d -t usbcheck.XXXX')
394 self.servo.system('mount -o ro %s %s' % (rootfs, tmpd))
395
396 if install_shim:
397 dir_list = self.servo.system_output('ls -a %s' %
398 os.path.join(tmpd, 'root'))
399 check_passed = '.factory_installer' in dir_list
400 else:
401 check_passed = self.servo.system_output(
402 'grep -i "CHROMEOS_RELEASE_DESCRIPTION=.*test" %s' %
403 os.path.join(tmpd, 'etc/lsb-release'),
404 ignore_status=True)
405 for cmd in ('umount %s' % rootfs, 'sync', 'rm -rf %s' % tmpd):
406 self.servo.system(cmd)
407
408 if not check_passed:
409 raise error.TestError(
410 'No Chrome OS %s found on the USB flash plugged into servo' %
411 'install shim' if install_shim else 'test')
412
Tom Wai-Hong Tam01d5e572012-10-23 10:07:11 +0800413 self.mark_setup_done('usb_check')
Tom Wai-Hong Tam76c75072011-10-25 18:00:12 +0800414
415
Tom Wai-Hong Tama6b382c2012-11-14 09:31:02 +0800416 def setup_usbkey(self, usbkey, host=None, install_shim=False):
Tom Wai-Hong Tam893bcc02012-11-02 16:13:34 +0800417 """Setup the USB disk for the test.
418
419 It checks the setup of USB disk and a valid ChromeOS test image inside.
420 It also muxes the USB disk to either the host or DUT by request.
421
422 Args:
423 usbkey: True if the USB disk is required for the test, False if not
424 required.
425 host: Optional, True to mux the USB disk to host, False to mux it
426 to DUT, default to do nothing.
Tom Wai-Hong Tama6b382c2012-11-14 09:31:02 +0800427 install_shim: True to verify an install shim instead of a test image.
Tom Wai-Hong Tam893bcc02012-11-02 16:13:34 +0800428 """
429 if usbkey:
Tom Wai-Hong Tama6b382c2012-11-14 09:31:02 +0800430 self.assert_test_image_in_usb_disk(install_shim=install_shim)
Tom Wai-Hong Tam893bcc02012-11-02 16:13:34 +0800431 elif host is None:
432 # USB disk is not required for the test. Better to mux it to host.
433 host = True
434
435 if host is True:
Vadim Bendeburye7bd9362012-12-19 14:35:20 -0800436 self.servo.switch_usbkey('host')
Tom Wai-Hong Tam893bcc02012-11-02 16:13:34 +0800437 elif host is False:
Vadim Bendeburye7bd9362012-12-19 14:35:20 -0800438 self.servo.switch_usbkey('dut')
Tom Wai-Hong Tam893bcc02012-11-02 16:13:34 +0800439
440
Tom Wai-Hong Tame796de42012-10-16 19:42:20 +0800441 def get_server_address(self):
442 """Get the server address seen from the client.
443
444 Returns:
445 A string of the server address.
446 """
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800447 r = self.faft_client.system.run_shell_command_get_output(
448 "echo $SSH_CLIENT")
Tom Wai-Hong Tame796de42012-10-16 19:42:20 +0800449 return r[0].split()[0]
450
451
Simran Basi741b5d42012-05-18 11:27:15 -0700452 def install_test_image(self, image_path=None, firmware_update=False):
Tom Wai-Hong Tam40fd9472012-01-09 17:11:02 +0800453 """Install the test image specied by the path onto the USB and DUT disk.
454
455 The method first copies the image to USB disk and reboots into it via
Mike Truty49153d82012-08-21 22:27:30 -0500456 recovery mode. Then runs 'chromeos-install' (and possible
457 chromeos-firmwareupdate') to install it to DUT disk.
458
459 Sample command line:
460
461 run_remote_tests.sh --servo --board=daisy --remote=w.x.y.z \
462 --args="image=/tmp/chromiumos_test_image.bin firmware_update=True" \
463 server/site_tests/firmware_XXXX/control
464
465 This test requires an automated recovery to occur while simulating
466 inserting and removing the usb key from the servo. To allow this the
467 following hardware setup is required:
468 1. servo2 board connected via servoflex.
469 2. USB key inserted in the servo2.
470 3. servo2 connected to the dut via dut_hub_in in the usb 2.0 slot.
471 4. network connected via usb dongle in the dut in usb 3.0 slot.
Tom Wai-Hong Tam40fd9472012-01-09 17:11:02 +0800472
473 Args:
Tom Wai-Hong Tame796de42012-10-16 19:42:20 +0800474 image_path: An URL or a path on the host to the test image.
Tom Wai-Hong Tam1a3ff742012-01-11 16:36:46 +0800475 firmware_update: Also update the firmware after installing.
Tom Wai-Hong Tam71818d82012-10-24 14:57:43 +0800476
477 Raises:
478 error.TestError: If devserver failed to start.
Tom Wai-Hong Tam40fd9472012-01-09 17:11:02 +0800479 """
Tom Wai-Hong Tam19ad9682012-10-24 09:33:42 +0800480 if not image_path:
481 return
482
Tom Wai-Hong Tam73229372012-10-23 11:58:16 +0800483 if self.check_setup_done('reimage'):
484 return
485
Tom Wai-Hong Tame796de42012-10-16 19:42:20 +0800486 if image_path.startswith(self._HTTP_PREFIX):
487 # TODO(waihong@chromium.org): Add the check of the URL to ensure
488 # it is a test image.
489 devserver = None
490 image_url = image_path
Tom Wai-Hong Tam42f136d2012-10-26 11:11:23 +0800491 elif self.servo.is_localhost():
Tom Wai-Hong Tam42f136d2012-10-26 11:11:23 +0800492 # If servod is localhost, i.e. both servod and FAFT see the same
493 # file system, do nothing.
494 devserver = None
495 image_url = image_path
Tom Wai-Hong Tame796de42012-10-16 19:42:20 +0800496 else:
Tom Wai-Hong Tame796de42012-10-16 19:42:20 +0800497 image_dir, image_base = os.path.split(image_path)
498 logging.info('Starting devserver to serve the image...')
499 # The following stdout and stderr arguments should not be None,
500 # even we don't use them. Otherwise, the socket of devserve is
501 # created as fd 1 (as no stdout) but it still thinks stdout is fd
502 # 1 and dump the log to the socket. Wrong HTTP protocol happens.
Tom Wai-Hong Tam71818d82012-10-24 14:57:43 +0800503 devserver = subprocess.Popen(['/usr/lib/devserver/devserver.py',
Tom Wai-Hong Tame796de42012-10-16 19:42:20 +0800504 '--archive_dir=%s' % image_dir,
505 '--port=%s' % self._DEVSERVER_PORT],
506 stdout=subprocess.PIPE,
507 stderr=subprocess.PIPE)
508 image_url = '%s%s:%s/static/archive/%s' % (
509 self._HTTP_PREFIX,
510 self.get_server_address(),
511 self._DEVSERVER_PORT,
512 image_base)
513
Tom Wai-Hong Tam71818d82012-10-24 14:57:43 +0800514 # Wait devserver startup completely
Tom Wai-Hong Tam41738762012-10-29 14:32:39 +0800515 time.sleep(self.delay.devserver)
Tom Wai-Hong Tam71818d82012-10-24 14:57:43 +0800516 # devserver is a service running forever. If it is terminated,
517 # some error does happen.
518 if devserver.poll():
519 raise error.TestError('Starting devserver failed, '
520 'returning %d.' % devserver.returncode)
521
Vic Yang772df8a2012-10-31 10:10:49 +0800522 logging.info('Ask Servo to install the image from %s', image_url)
Tom Wai-Hong Tame796de42012-10-16 19:42:20 +0800523 self.servo.image_to_servo_usb(image_url)
524
Vadim Bendebury89ec24e2012-12-17 12:54:18 -0800525 self.assert_test_image_in_usb_disk()
526
Tom Wai-Hong Tame796de42012-10-16 19:42:20 +0800527 if devserver and devserver.poll() is None:
528 logging.info('Shutting down devserver...')
529 devserver.terminate()
Mike Truty49153d82012-08-21 22:27:30 -0500530
531 # DUT is powered off while imaging servo USB.
532 # Now turn it on.
533 self.servo.power_short_press()
534 self.wait_for_client()
Vadim Bendeburye7bd9362012-12-19 14:35:20 -0800535 self.servo.switch_usbkey('dut')
Mike Truty49153d82012-08-21 22:27:30 -0500536
537 install_cmd = 'chromeos-install --yes'
538 if firmware_update:
539 install_cmd += ' && chromeos-firmwareupdate --mode recovery'
Tom Wai-Hong Tam1dd11592012-10-26 15:01:45 +0800540 self.backup_firmware()
Mike Truty49153d82012-08-21 22:27:30 -0500541
542 self.register_faft_sequence((
543 { # Step 1, request recovery boot
Vic Yangf93f7022012-10-31 09:40:36 +0800544 'state_checker': (self.checkers.crossystem_checker, {
Mike Truty49153d82012-08-21 22:27:30 -0500545 'mainfw_type': ('developer', 'normal'),
546 }),
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800547 'userspace_action': (
548 self.faft_client.system.request_recovery_boot),
Mike Truty49153d82012-08-21 22:27:30 -0500549 'firmware_action': self.wait_fw_screen_and_plug_usb,
550 'install_deps_after_boot': True,
551 },
552 { # Step 2, expected recovery boot
Vic Yangf93f7022012-10-31 09:40:36 +0800553 'state_checker': (self.checkers.crossystem_checker, {
Mike Truty49153d82012-08-21 22:27:30 -0500554 'mainfw_type': 'recovery',
Tom Wai-Hong Tam6ec46e32012-10-05 16:39:21 +0800555 'recovery_reason' : vboot.RECOVERY_REASON['US_TEST'],
Mike Truty49153d82012-08-21 22:27:30 -0500556 }),
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800557 'userspace_action': (self.faft_client.system.run_shell_command,
Mike Truty49153d82012-08-21 22:27:30 -0500558 install_cmd),
559 'reboot_action': self.cold_reboot,
560 'install_deps_after_boot': True,
561 },
562 { # Step 3, expected normal or developer boot (not recovery)
Vic Yangf93f7022012-10-31 09:40:36 +0800563 'state_checker': (self.checkers.crossystem_checker, {
Mike Truty49153d82012-08-21 22:27:30 -0500564 'mainfw_type': ('developer', 'normal')
565 }),
566 },
567 ))
568 self.run_faft_sequence()
Tom Wai-Hong Tam1dd11592012-10-26 15:01:45 +0800569
570 if firmware_update:
571 self.clear_saved_firmware()
572
Mike Truty49153d82012-08-21 22:27:30 -0500573 # 'Unplug' any USB keys in the servo from the dut.
Vadim Bendeburye7bd9362012-12-19 14:35:20 -0800574 self.servo.switch_usbkey('host')
Tom Wai-Hong Tam6668b762012-10-23 11:45:36 +0800575 # Mark usb_check done so it won't check a test image in USB anymore.
576 self.mark_setup_done('usb_check')
Tom Wai-Hong Tam73229372012-10-23 11:58:16 +0800577 self.mark_setup_done('reimage')
Tom Wai-Hong Tam40fd9472012-01-09 17:11:02 +0800578
579
Tom Wai-Hong Tamfa3142e2012-08-16 11:53:58 +0800580 def clear_set_gbb_flags(self, clear_mask, set_mask):
581 """Clear and set the GBB flags in the current flashrom.
Tom Wai-Hong Tam15ce5812012-07-26 14:14:18 +0800582
583 Args:
Tom Wai-Hong Tamfa3142e2012-08-16 11:53:58 +0800584 clear_mask: A mask of flags to be cleared.
585 set_mask: A mask of flags to be set.
Tom Wai-Hong Tam15ce5812012-07-26 14:14:18 +0800586 """
Tom Wai-Hong Tamc1a569f2012-12-04 15:07:25 +0800587 gbb_flags = self.faft_client.bios.get_gbb_flags()
Tom Wai-Hong Tamfa3142e2012-08-16 11:53:58 +0800588 new_flags = gbb_flags & ctypes.c_uint32(~clear_mask).value | set_mask
589
590 if (gbb_flags != new_flags):
Vic Yang772df8a2012-10-31 10:10:49 +0800591 logging.info('Change the GBB flags from 0x%x to 0x%x.',
592 gbb_flags, new_flags)
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800593 self.faft_client.system.run_shell_command(
Tom Wai-Hong Tamfda76e22012-08-08 17:19:10 +0800594 '/usr/share/vboot/bin/set_gbb_flags.sh 0x%x' % new_flags)
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800595 self.faft_client.bios.reload()
Tom Wai-Hong Tama2481922012-08-08 17:24:42 +0800596 # If changing FORCE_DEV_SWITCH_ON flag, reboot to get a clear state
Tom Wai-Hong Tam6ec46e32012-10-05 16:39:21 +0800597 if ((gbb_flags ^ new_flags) & vboot.GBB_FLAG_FORCE_DEV_SWITCH_ON):
Tom Wai-Hong Tama2481922012-08-08 17:24:42 +0800598 self.run_faft_step({
Tom Wai-Hong Tam56977782012-11-23 16:13:28 +0800599 'firmware_action': self.wait_dev_screen_and_ctrl_d,
Tom Wai-Hong Tama2481922012-08-08 17:24:42 +0800600 })
Tom Wai-Hong Tam15ce5812012-07-26 14:14:18 +0800601
602
Vic Yang772df8a2012-10-31 10:10:49 +0800603 def check_ec_capability(self, required_cap=None, suppress_warning=False):
Vic Yang4d72cb62012-07-24 11:51:09 +0800604 """Check if current platform has required EC capabilities.
605
606 Args:
607 required_cap: A list containing required EC capabilities. Pass in
608 None to only check for presence of Chrome EC.
Tom Wai-Hong Tamb8a91392012-09-27 10:45:32 +0800609 suppress_warning: True to suppress any warning messages.
Vic Yang4d72cb62012-07-24 11:51:09 +0800610
611 Returns:
612 True if requirements are met. Otherwise, False.
613 """
614 if not self.client_attr.chrome_ec:
Tom Wai-Hong Tamb8a91392012-09-27 10:45:32 +0800615 if not suppress_warning:
616 logging.warn('Requires Chrome EC to run this test.')
Vic Yang4d72cb62012-07-24 11:51:09 +0800617 return False
618
Vic Yang772df8a2012-10-31 10:10:49 +0800619 if not required_cap:
620 return True
621
Vic Yang4d72cb62012-07-24 11:51:09 +0800622 for cap in required_cap:
623 if cap not in self.client_attr.ec_capability:
Tom Wai-Hong Tamb8a91392012-09-27 10:45:32 +0800624 if not suppress_warning:
625 logging.warn('Requires EC capability "%s" to run this '
Vic Yang772df8a2012-10-31 10:10:49 +0800626 'test.', cap)
Vic Yang4d72cb62012-07-24 11:51:09 +0800627 return False
628
629 return True
630
631
Tom Wai-Hong Tam07278c22012-02-08 16:53:00 +0800632 def check_root_part_on_non_recovery(self, part):
633 """Check the partition number of root device and on normal/dev boot.
634
635 Returns:
636 True if the root device matched and on normal/dev boot;
637 otherwise, False.
638 """
Vic Yangf93f7022012-10-31 09:40:36 +0800639 return self.checkers.root_part_checker(part) and \
640 self.checkers.crossystem_checker({
Tom Wai-Hong Tam07278c22012-02-08 16:53:00 +0800641 'mainfw_type': ('normal', 'developer'),
Tom Wai-Hong Tam07278c22012-02-08 16:53:00 +0800642 })
643
644
Tom Wai-Hong Tamf2103be2011-11-10 07:26:56 +0800645 def _join_part(self, dev, part):
646 """Return a concatenated string of device and partition number.
647
648 Args:
649 dev: A string of device, e.g.'/dev/sda'.
650 part: A string of partition number, e.g.'3'.
651
652 Returns:
653 A concatenated string of device and partition number, e.g.'/dev/sda3'.
654
655 >>> seq = FAFTSequence()
656 >>> seq._join_part('/dev/sda', '3')
657 '/dev/sda3'
658 >>> seq._join_part('/dev/mmcblk0', '2')
659 '/dev/mmcblk0p2'
660 """
661 if 'mmcblk' in dev:
662 return dev + 'p' + part
663 else:
664 return dev + part
665
666
Tom Wai-Hong Tamcfda61f2011-11-02 17:41:01 +0800667 def copy_kernel_and_rootfs(self, from_part, to_part):
668 """Copy kernel and rootfs from from_part to to_part.
669
670 Args:
671 from_part: A string of partition number to be copied from.
Tom Wai-Hong Tamf2103be2011-11-10 07:26:56 +0800672 to_part: A string of partition number to be copied to.
Tom Wai-Hong Tamcfda61f2011-11-02 17:41:01 +0800673 """
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800674 root_dev = self.faft_client.system.get_root_dev()
Vic Yang772df8a2012-10-31 10:10:49 +0800675 logging.info('Copying kernel from %s to %s. Please wait...',
Vic Yang55f31252012-11-01 17:07:54 +0800676 from_part, to_part)
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800677 self.faft_client.system.run_shell_command('dd if=%s of=%s bs=4M' %
Tom Wai-Hong Tamf2103be2011-11-10 07:26:56 +0800678 (self._join_part(root_dev, self.KERNEL_MAP[from_part]),
679 self._join_part(root_dev, self.KERNEL_MAP[to_part])))
Vic Yang772df8a2012-10-31 10:10:49 +0800680 logging.info('Copying rootfs from %s to %s. Please wait...',
Vic Yang55f31252012-11-01 17:07:54 +0800681 from_part, to_part)
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800682 self.faft_client.system.run_shell_command('dd if=%s of=%s bs=4M' %
Tom Wai-Hong Tamf2103be2011-11-10 07:26:56 +0800683 (self._join_part(root_dev, self.ROOTFS_MAP[from_part]),
684 self._join_part(root_dev, self.ROOTFS_MAP[to_part])))
Tom Wai-Hong Tamcfda61f2011-11-02 17:41:01 +0800685
686
687 def ensure_kernel_boot(self, part):
688 """Ensure the request kernel boot.
689
690 If not, it duplicates the current kernel to the requested kernel
691 and sets the requested higher priority to ensure it boot.
692
693 Args:
Tom Wai-Hong Tama9c1a502011-11-10 06:39:26 +0800694 part: A string of kernel partition number or 'a'/'b'.
Tom Wai-Hong Tamcfda61f2011-11-02 17:41:01 +0800695 """
Vic Yangf93f7022012-10-31 09:40:36 +0800696 if not self.checkers.root_part_checker(part):
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800697 if self.faft_client.kernel.diff_a_b():
Tom Wai-Hong Tam622d0ba2012-08-15 16:29:05 +0800698 self.copy_kernel_and_rootfs(
699 from_part=self.OTHER_KERNEL_MAP[part],
700 to_part=part)
Tom Wai-Hong Tamc7ecfca2011-12-06 11:12:31 +0800701 self.run_faft_step({
702 'userspace_action': (self.reset_and_prioritize_kernel, part),
703 })
Tom Wai-Hong Tamcfda61f2011-11-02 17:41:01 +0800704
705
Tom Wai-Hong Tam05574ee2012-10-30 11:34:21 +0800706 def set_hardware_write_protect(self, enable):
Vic Yang2cabf812012-08-28 02:39:04 +0800707 """Set hardware write protect pin.
708
709 Args:
710 enable: True if asserting write protect pin. Otherwise, False.
711 """
712 self.servo.set('fw_wp_vref', self.client_attr.wp_voltage)
713 self.servo.set('fw_wp_en', 'on')
Tom Wai-Hong Tam05574ee2012-10-30 11:34:21 +0800714 self.servo.set('fw_wp', 'on' if enable else 'off')
Vic Yang416f2032012-08-28 10:18:03 +0800715
716
Tom Wai-Hong Tam44204b32012-11-20 13:55:40 +0800717 def set_ec_write_protect_and_reboot(self, enable):
Vic Yang416f2032012-08-28 10:18:03 +0800718 """Set EC write protect status and reboot to take effect.
719
Tom Wai-Hong Tam44204b32012-11-20 13:55:40 +0800720 The write protect state is only activated if both hardware write
721 protect pin is asserted and software write protect flag is set.
Vic Yang416f2032012-08-28 10:18:03 +0800722 This method asserts/deasserts hardware write protect pin first, and
723 set corresponding EC software write protect flag.
724
Tom Wai-Hong Tam44204b32012-11-20 13:55:40 +0800725 If the device uses non-Chrome EC, set the software write protect via
726 flashrom.
727
728 If the device uses Chrome EC, a reboot is required for write protect
729 to take effect. Since the software write protect flag cannot be unset
730 if hardware write protect pin is asserted, we need to deasserted the
731 pin first if we are deactivating write protect. Similarly, a reboot
732 is required before we can modify the software flag.
733
Vic Yang416f2032012-08-28 10:18:03 +0800734 Args:
735 enable: True if activating EC write protect. Otherwise, False.
736 """
Tom Wai-Hong Tam05574ee2012-10-30 11:34:21 +0800737 self.set_hardware_write_protect(enable)
Tom Wai-Hong Tam44204b32012-11-20 13:55:40 +0800738 if self.client_attr.chrome_ec:
739 self.set_chrome_ec_write_protect_and_reboot(enable)
740 else:
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800741 self.faft_client.ec.set_write_protect(enable)
Tom Wai-Hong Tam44204b32012-11-20 13:55:40 +0800742 self.sync_and_warm_reboot()
743
744
745 def set_chrome_ec_write_protect_and_reboot(self, enable):
746 """Set Chrome EC write protect status and reboot to take effect.
747
748 Args:
749 enable: True if activating EC write protect. Otherwise, False.
750 """
Tom Wai-Hong Tam05574ee2012-10-30 11:34:21 +0800751 if enable:
Vic Yang416f2032012-08-28 10:18:03 +0800752 # Set write protect flag and reboot to take effect.
Tom Wai-Hong Tam05574ee2012-10-30 11:34:21 +0800753 self.ec.set_flash_write_protect(enable)
Vic Yang416f2032012-08-28 10:18:03 +0800754 self.sync_and_ec_reboot()
755 else:
756 # Reboot after deasserting hardware write protect pin to deactivate
757 # write protect. And then remove software write protect flag.
758 self.sync_and_ec_reboot()
Tom Wai-Hong Tam05574ee2012-10-30 11:34:21 +0800759 self.ec.set_flash_write_protect(enable)
Vic Yang2cabf812012-08-28 02:39:04 +0800760
761
Tom Wai-Hong Tam700c9fd2012-11-15 18:18:30 +0800762 def setup_ec_write_protect(self, ec_wp):
763 """Setup for EC write-protection.
764
765 It makes sure the EC in the requested write-protection state. If not, it
766 flips the state. Flipping the write-protection requires DUT reboot.
767
768 Args:
769 ec_wp: True to request EC write-protected; False to request EC not
770 write-protected; None to do nothing.
771 """
772 if ec_wp is None:
773 self._old_ec_wp = None
774 return
775 self._old_ec_wp = self.checkers.crossystem_checker({'wpsw_boot': '1'})
776 if ec_wp != self._old_ec_wp:
777 logging.info('The test required EC is %swrite-protected. Reboot '
778 'and flip the state.', '' if ec_wp else 'not ')
779 self.run_faft_step({
Tom Wai-Hong Tamdd830982013-01-16 10:31:05 +0800780 'reboot_action': (self.set_ec_write_protect_and_reboot, ec_wp),
781 'firmware_action': self.wait_dev_screen_and_ctrl_d,
Tom Wai-Hong Tam700c9fd2012-11-15 18:18:30 +0800782 })
783
784
785 def restore_ec_write_protect(self):
786 """Restore the original EC write-protection."""
787 if self._old_ec_wp is None:
788 return
789 if not self.checkers.crossystem_checker(
790 {'wpsw_boot': '1' if self._old_ec_wp else '0'}):
791 logging.info('Restore the original EC write protection and reboot.')
792 self.run_faft_step({
Tom Wai-Hong Tam44204b32012-11-20 13:55:40 +0800793 'reboot_action': (self.set_ec_write_protect_and_reboot,
Tom Wai-Hong Tamdd830982013-01-16 10:31:05 +0800794 self._old_ec_wp),
795 'firmware_action': self.wait_dev_screen_and_ctrl_d,
Tom Wai-Hong Tam700c9fd2012-11-15 18:18:30 +0800796 })
797
798
Tom Wai-Hong Tam91612bc2012-10-29 16:04:21 +0800799 def press_ctrl_d(self):
Tom Wai-Hong Tam1db43832011-12-09 10:50:56 +0800800 """Send Ctrl-D key to DUT."""
Tom Wai-Hong Tam9c15b4b2012-10-29 17:59:26 +0800801 if not self.client_attr.has_keyboard:
802 logging.info('Running usbkm232-ctrld...')
803 os.system('usbkm232-ctrld')
Tom Wai-Hong Tam1db43832011-12-09 10:50:56 +0800804 else:
805 self.servo.ctrl_d()
806
807
Tom Wai-Hong Tam91612bc2012-10-29 16:04:21 +0800808 def press_ctrl_u(self):
Tom Wai-Hong Tamadbec3e2012-10-15 14:20:15 +0800809 """Send Ctrl-U key to DUT.
810
811 Raises:
812 error.TestError: if a non-Chrome EC device or no Ctrl-U command given
813 on a no-build-in-keyboard device.
814 """
Tom Wai-Hong Tam9c15b4b2012-10-29 17:59:26 +0800815 if not self.client_attr.has_keyboard:
816 logging.info('Running usbkm232-ctrlu...')
817 os.system('usbkm232-ctrlu')
Tom Wai-Hong Tamadbec3e2012-10-15 14:20:15 +0800818 elif self.check_ec_capability(['keyboard'], suppress_warning=True):
819 self.ec.key_down('<ctrl_l>')
820 self.ec.key_down('u')
821 self.ec.key_up('u')
822 self.ec.key_up('<ctrl_l>')
823 elif self.client_attr.has_keyboard:
824 raise error.TestError(
825 "Can't send Ctrl-U to DUT without using Chrome EC.")
826 else:
827 raise error.TestError(
828 "Should specify the ctrl_u_cmd argument.")
829
830
Tom Wai-Hong Tam91612bc2012-10-29 16:04:21 +0800831 def press_enter(self):
Tom Wai-Hong Tam1db43832011-12-09 10:50:56 +0800832 """Send Enter key to DUT."""
Tom Wai-Hong Tam9c15b4b2012-10-29 17:59:26 +0800833 if not self.client_attr.has_keyboard:
834 logging.info('Running usbkm232-enter...')
835 os.system('usbkm232-enter')
Tom Wai-Hong Tam1db43832011-12-09 10:50:56 +0800836 else:
837 self.servo.enter_key()
838
839
Tom Wai-Hong Tam56977782012-11-23 16:13:28 +0800840 def wait_dev_screen_and_ctrl_d(self):
841 """Wait for firmware warning screen and press Ctrl-D."""
842 time.sleep(self.delay.dev_screen)
843 self.press_ctrl_d()
844
845
Tom Wai-Hong Tama9c1a502011-11-10 06:39:26 +0800846 def wait_fw_screen_and_ctrl_d(self):
847 """Wait for firmware warning screen and press Ctrl-D."""
Tom Wai-Hong Tam41738762012-10-29 14:32:39 +0800848 time.sleep(self.delay.firmware_screen)
Tom Wai-Hong Tam91612bc2012-10-29 16:04:21 +0800849 self.press_ctrl_d()
Tom Wai-Hong Tama9c1a502011-11-10 06:39:26 +0800850
851
Tom Wai-Hong Tamadbec3e2012-10-15 14:20:15 +0800852 def wait_fw_screen_and_ctrl_u(self):
853 """Wait for firmware warning screen and press Ctrl-U."""
Tom Wai-Hong Tam41738762012-10-29 14:32:39 +0800854 time.sleep(self.delay.firmware_screen)
Tom Wai-Hong Tam91612bc2012-10-29 16:04:21 +0800855 self.press_ctrl_u()
Tom Wai-Hong Tamadbec3e2012-10-15 14:20:15 +0800856
857
Tom Wai-Hong Tam78709592011-12-19 11:16:50 +0800858 def wait_fw_screen_and_trigger_recovery(self, need_dev_transition=False):
859 """Wait for firmware warning screen and trigger recovery boot."""
Tom Wai-Hong Tam41738762012-10-29 14:32:39 +0800860 time.sleep(self.delay.firmware_screen)
Tom Wai-Hong Tam91612bc2012-10-29 16:04:21 +0800861 self.press_enter()
Tom Wai-Hong Tam78709592011-12-19 11:16:50 +0800862
863 # For Alex/ZGB, there is a dev warning screen in text mode.
864 # Skip it by pressing Ctrl-D.
865 if need_dev_transition:
Tom Wai-Hong Tam41738762012-10-29 14:32:39 +0800866 time.sleep(self.delay.legacy_text_screen)
Tom Wai-Hong Tam91612bc2012-10-29 16:04:21 +0800867 self.press_ctrl_d()
Tom Wai-Hong Tam78709592011-12-19 11:16:50 +0800868
869
Mike Truty49153d82012-08-21 22:27:30 -0500870 def wait_fw_screen_and_unplug_usb(self):
871 """Wait for firmware warning screen and then unplug the servo USB."""
Tom Wai-Hong Tam41738762012-10-29 14:32:39 +0800872 time.sleep(self.delay.load_usb)
Vadim Bendeburye7bd9362012-12-19 14:35:20 -0800873 self.servo.switch_usbkey('host')
Tom Wai-Hong Tam41738762012-10-29 14:32:39 +0800874 time.sleep(self.delay.between_usb_plug)
Mike Truty49153d82012-08-21 22:27:30 -0500875
876
877 def wait_fw_screen_and_plug_usb(self):
878 """Wait for firmware warning screen and then unplug and plug the USB."""
879 self.wait_fw_screen_and_unplug_usb()
Vadim Bendeburye7bd9362012-12-19 14:35:20 -0800880 self.servo.switch_usbkey('dut')
Tom Wai-Hong Tam5d2f4702011-12-06 10:42:31 +0800881
882
Tom Wai-Hong Tam78709592011-12-19 11:16:50 +0800883 def wait_fw_screen_and_press_power(self):
884 """Wait for firmware warning screen and press power button."""
Tom Wai-Hong Tam41738762012-10-29 14:32:39 +0800885 time.sleep(self.delay.firmware_screen)
Tom Wai-Hong Tam7317c042012-08-14 11:59:06 +0800886 # While the firmware screen, the power button probing loop sleeps
887 # 0.25 second on every scan. Use the normal delay (1.2 second) for
888 # power press.
889 self.servo.power_normal_press()
Tom Wai-Hong Tam78709592011-12-19 11:16:50 +0800890
891
Tom Wai-Hong Tam4f5e5922012-07-27 16:23:15 +0800892 def wait_longer_fw_screen_and_press_power(self):
893 """Wait for firmware screen without timeout and press power button."""
Tom Wai-Hong Tam41738762012-10-29 14:32:39 +0800894 time.sleep(self.delay.dev_screen_timeout)
Tom Wai-Hong Tam4f5e5922012-07-27 16:23:15 +0800895 self.wait_fw_screen_and_press_power()
896
897
Tom Wai-Hong Tam78709592011-12-19 11:16:50 +0800898 def wait_fw_screen_and_close_lid(self):
899 """Wait for firmware warning screen and close lid."""
Tom Wai-Hong Tam41738762012-10-29 14:32:39 +0800900 time.sleep(self.delay.firmware_screen)
Tom Wai-Hong Tam78709592011-12-19 11:16:50 +0800901 self.servo.lid_close()
902
903
Tom Wai-Hong Tam473cfa72012-07-27 17:16:57 +0800904 def wait_longer_fw_screen_and_close_lid(self):
905 """Wait for firmware screen without timeout and close lid."""
Tom Wai-Hong Tam41738762012-10-29 14:32:39 +0800906 time.sleep(self.delay.firmware_screen)
Tom Wai-Hong Tam473cfa72012-07-27 17:16:57 +0800907 self.wait_fw_screen_and_close_lid()
908
909
Tom Wai-Hong Tam01d5e572012-10-23 10:07:11 +0800910 def setup_gbb_flags(self):
911 """Setup the GBB flags for FAFT test."""
912 if self.check_setup_done('gbb_flags'):
913 return
914
915 logging.info('Set proper GBB flags for test.')
916 self.clear_set_gbb_flags(vboot.GBB_FLAG_DEV_SCREEN_SHORT_DELAY |
917 vboot.GBB_FLAG_FORCE_DEV_SWITCH_ON |
918 vboot.GBB_FLAG_FORCE_DEV_BOOT_USB |
919 vboot.GBB_FLAG_DISABLE_FW_ROLLBACK_CHECK,
Gediminas Ramanauskasba352ad2012-11-09 09:43:32 -0800920 vboot.GBB_FLAG_ENTER_TRIGGERS_TONORM |
921 vboot.GBB_FLAG_FAFT_KEY_OVERIDE)
Tom Wai-Hong Tam01d5e572012-10-23 10:07:11 +0800922 self.mark_setup_done('gbb_flags')
923
924
Tom Wai-Hong Tamfd590c92011-11-25 11:50:57 +0800925 def setup_tried_fwb(self, tried_fwb):
926 """Setup for fw B tried state.
927
928 It makes sure the system in the requested fw B tried state. If not, it
929 tries to do so.
930
931 Args:
932 tried_fwb: True if requested in tried_fwb=1; False if tried_fwb=0.
933 """
934 if tried_fwb:
Vic Yangf93f7022012-10-31 09:40:36 +0800935 if not self.checkers.crossystem_checker({'tried_fwb': '1'}):
Tom Wai-Hong Tamfd590c92011-11-25 11:50:57 +0800936 logging.info(
937 'Firmware is not booted with tried_fwb. Reboot into it.')
938 self.run_faft_step({
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800939 'userspace_action': self.faft_client.system.set_try_fw_b,
Tom Wai-Hong Tamfd590c92011-11-25 11:50:57 +0800940 })
941 else:
Vic Yangf93f7022012-10-31 09:40:36 +0800942 if not self.checkers.crossystem_checker({'tried_fwb': '0'}):
Tom Wai-Hong Tamfd590c92011-11-25 11:50:57 +0800943 logging.info(
944 'Firmware is booted with tried_fwb. Reboot to clear.')
945 self.run_faft_step({})
946
947
Tom Wai-Hong Tama373f802012-07-31 21:16:48 +0800948 def enable_rec_mode_and_reboot(self):
949 """Switch to rec mode and reboot.
950
951 This method emulates the behavior of the old physical recovery switch,
952 i.e. switch ON + reboot + switch OFF, and the new keyboard controlled
953 recovery mode, i.e. just press Power + Esc + Refresh.
954 """
Tom Wai-Hong Tam80419a82012-10-30 09:10:00 +0800955 if self.client_attr.chrome_ec:
Tom Wai-Hong Tam41128082012-11-16 12:02:45 +0800956 # Reset twice to emulate a long recovery-key-combo hold.
957 cold_reset_num = 2 if self.client_attr.long_rec_combo else 1
Tom Wai-Hong Tam4c9684a2012-12-11 10:48:05 +0800958 for i in range(cold_reset_num):
959 if i:
960 time.sleep(self.delay.ec_boot_to_console)
Tom Wai-Hong Tam41128082012-11-16 12:02:45 +0800961 # Cold reset to clear EC_IN_RW signal
962 self.servo.set('cold_reset', 'on')
963 time.sleep(self.delay.hold_cold_reset)
964 self.servo.set('cold_reset', 'off')
Tom Wai-Hong Tambb92e6c2012-10-30 11:06:09 +0800965 self.ec.reboot("ap-off")
Tom Wai-Hong Tam41738762012-10-29 14:32:39 +0800966 time.sleep(self.delay.ec_boot_to_console)
Tom Wai-Hong Tam665281c2012-10-30 11:55:10 +0800967 self.ec.set_hostevent(chrome_ec.HOSTEVENT_KEYBOARD_RECOVERY)
Vic Yang611dd852012-08-02 15:36:31 +0800968 self.servo.power_short_press()
Gediminas Ramanauskasba352ad2012-11-09 09:43:32 -0800969 elif self.client_attr.broken_rec_mode:
Tom Wai-Hong Tamc5c14ef2012-11-20 16:33:37 +0800970 if self._host and self._host.has_power():
Gediminas Ramanauskasba352ad2012-11-09 09:43:32 -0800971 self._host.power_cycle()
972 else:
973 logging.info('You have %d seconds to power cycle this device.',
974 self.delay.user_power_cycle)
975 time.sleep(self.delay.user_power_cycle)
976 logging.info('Booting to recovery mode.')
977 self.servo.custom_recovery_mode()
Tom Wai-Hong Tamac943172012-08-01 10:38:39 +0800978 else:
979 self.servo.enable_recovery_mode()
980 self.cold_reboot()
Tom Wai-Hong Tamad4aaae2012-12-12 11:02:06 +0800981 time.sleep(self.delay.ec_boot_to_console)
Tom Wai-Hong Tamac943172012-08-01 10:38:39 +0800982 self.servo.disable_recovery_mode()
Tom Wai-Hong Tama373f802012-07-31 21:16:48 +0800983
984
Tom Wai-Hong Tam0b9e6d72012-07-31 20:54:06 +0800985 def enable_dev_mode_and_reboot(self):
986 """Switch to developer mode and reboot."""
Vic Yange7553162012-06-20 16:20:47 +0800987 if self.client_attr.keyboard_dev:
988 self.enable_keyboard_dev_mode()
989 else:
990 self.servo.enable_development_mode()
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800991 self.faft_client.system.run_shell_command(
Vic Yange7553162012-06-20 16:20:47 +0800992 'chromeos-firmwareupdate --mode todev && reboot')
Tom Wai-Hong Tam78709592011-12-19 11:16:50 +0800993
994
Tom Wai-Hong Tam0b9e6d72012-07-31 20:54:06 +0800995 def enable_normal_mode_and_reboot(self):
996 """Switch to normal mode and reboot."""
Vic Yange7553162012-06-20 16:20:47 +0800997 if self.client_attr.keyboard_dev:
998 self.disable_keyboard_dev_mode()
999 else:
1000 self.servo.disable_development_mode()
Chun-ting Changd43aa9b2012-11-16 10:12:05 +08001001 self.faft_client.system.run_shell_command(
Vic Yange7553162012-06-20 16:20:47 +08001002 'chromeos-firmwareupdate --mode tonormal && reboot')
1003
1004
1005 def wait_fw_screen_and_switch_keyboard_dev_mode(self, dev):
1006 """Wait for firmware screen and then switch into or out of dev mode.
1007
1008 Args:
1009 dev: True if switching into dev mode. Otherwise, False.
1010 """
Tom Wai-Hong Tam41738762012-10-29 14:32:39 +08001011 time.sleep(self.delay.firmware_screen)
Vic Yange7553162012-06-20 16:20:47 +08001012 if dev:
Tom Wai-Hong Tam91612bc2012-10-29 16:04:21 +08001013 self.press_ctrl_d()
Vic Yange7553162012-06-20 16:20:47 +08001014 else:
Tom Wai-Hong Tam91612bc2012-10-29 16:04:21 +08001015 self.press_enter()
Vic Yang0dc84b82012-10-31 12:29:39 +08001016 time.sleep(self.delay.confirm_screen)
Tom Wai-Hong Tam91612bc2012-10-29 16:04:21 +08001017 self.press_enter()
Vic Yange7553162012-06-20 16:20:47 +08001018
1019
1020 def enable_keyboard_dev_mode(self):
1021 logging.info("Enabling keyboard controlled developer mode")
Tom Wai-Hong Tamf1a17d72012-07-26 11:39:52 +08001022 # Plug out USB disk for preventing recovery boot without warning
Vadim Bendeburye7bd9362012-12-19 14:35:20 -08001023 self.servo.switch_usbkey('host')
Vic Yange7553162012-06-20 16:20:47 +08001024 # Rebooting EC with rec mode on. Should power on AP.
Tom Wai-Hong Tama373f802012-07-31 21:16:48 +08001025 self.enable_rec_mode_and_reboot()
Tom Wai-Hong Tam8c54eb82012-08-01 10:31:07 +08001026 self.wait_for_client_offline()
Vic Yange7553162012-06-20 16:20:47 +08001027 self.wait_fw_screen_and_switch_keyboard_dev_mode(dev=True)
Vic Yange7553162012-06-20 16:20:47 +08001028
Gediminas Ramanauskas9da80f22012-11-14 12:59:43 -08001029 # TODO (crosbug.com/p/16231) remove this conditional completely if/when
1030 # issue is resolved.
1031 if self.client_attr.platform == 'Parrot':
1032 self.wait_for_client_offline()
1033 self.cold_reboot()
1034
Vic Yange7553162012-06-20 16:20:47 +08001035
1036 def disable_keyboard_dev_mode(self):
1037 logging.info("Disabling keyboard controlled developer mode")
Gediminas Ramanauskasba352ad2012-11-09 09:43:32 -08001038 if (not self.client_attr.chrome_ec and
1039 not self.client_attr.broken_rec_mode):
Vic Yang611dd852012-08-02 15:36:31 +08001040 self.servo.disable_recovery_mode()
Tom Wai-Hong Tam7ad99ab2012-07-30 19:30:51 +08001041 self.cold_reboot()
Tom Wai-Hong Tam8c54eb82012-08-01 10:31:07 +08001042 self.wait_for_client_offline()
Vic Yange7553162012-06-20 16:20:47 +08001043 self.wait_fw_screen_and_switch_keyboard_dev_mode(dev=False)
Tom Wai-Hong Tam78709592011-12-19 11:16:50 +08001044
1045
Tom Wai-Hong Tama9c1a502011-11-10 06:39:26 +08001046 def setup_dev_mode(self, dev_mode):
1047 """Setup for development mode.
1048
Tom Wai-Hong Tamfd590c92011-11-25 11:50:57 +08001049 It makes sure the system in the requested normal/dev mode. If not, it
Tom Wai-Hong Tama9c1a502011-11-10 06:39:26 +08001050 tries to do so.
1051
1052 Args:
1053 dev_mode: True if requested in dev mode; False if normal mode.
1054 """
Tom Wai-Hong Tamfd590c92011-11-25 11:50:57 +08001055 # Change the default firmware_action for dev mode passing the fw screen.
1056 self.register_faft_template({
Tom Wai-Hong Tam56977782012-11-23 16:13:28 +08001057 'firmware_action': (self.wait_dev_screen_and_ctrl_d if dev_mode
Tom Wai-Hong Tamfd590c92011-11-25 11:50:57 +08001058 else None),
1059 })
Tom Wai-Hong Tama9c1a502011-11-10 06:39:26 +08001060 if dev_mode:
Vic Yange7553162012-06-20 16:20:47 +08001061 if (not self.client_attr.keyboard_dev and
Vic Yangf93f7022012-10-31 09:40:36 +08001062 not self.checkers.crossystem_checker({'devsw_cur': '1'})):
Tom Wai-Hong Tama9c1a502011-11-10 06:39:26 +08001063 logging.info('Dev switch is not on. Now switch it on.')
1064 self.servo.enable_development_mode()
Vic Yangf93f7022012-10-31 09:40:36 +08001065 if not self.checkers.crossystem_checker({'devsw_boot': '1',
Tom Wai-Hong Tama9c1a502011-11-10 06:39:26 +08001066 'mainfw_type': 'developer'}):
1067 logging.info('System is not in dev mode. Reboot into it.')
Tom Wai-Hong Tamfd590c92011-11-25 11:50:57 +08001068 self.run_faft_step({
Vic Yange7553162012-06-20 16:20:47 +08001069 'userspace_action': None if self.client_attr.keyboard_dev
Chun-ting Changd43aa9b2012-11-16 10:12:05 +08001070 else (self.faft_client.system.run_shell_command,
Tom Wai-Hong Tamc7ecfca2011-12-06 11:12:31 +08001071 'chromeos-firmwareupdate --mode todev && reboot'),
Vic Yange7553162012-06-20 16:20:47 +08001072 'reboot_action': self.enable_keyboard_dev_mode if
1073 self.client_attr.keyboard_dev else None,
Tom Wai-Hong Tamfd590c92011-11-25 11:50:57 +08001074 })
Tom Wai-Hong Tama9c1a502011-11-10 06:39:26 +08001075 else:
Vic Yange7553162012-06-20 16:20:47 +08001076 if (not self.client_attr.keyboard_dev and
Vic Yangf93f7022012-10-31 09:40:36 +08001077 not self.checkers.crossystem_checker({'devsw_cur': '0'})):
Tom Wai-Hong Tama9c1a502011-11-10 06:39:26 +08001078 logging.info('Dev switch is not off. Now switch it off.')
1079 self.servo.disable_development_mode()
Vic Yangf93f7022012-10-31 09:40:36 +08001080 if not self.checkers.crossystem_checker({'devsw_boot': '0',
Tom Wai-Hong Tama9c1a502011-11-10 06:39:26 +08001081 'mainfw_type': 'normal'}):
1082 logging.info('System is not in normal mode. Reboot into it.')
Tom Wai-Hong Tamfd590c92011-11-25 11:50:57 +08001083 self.run_faft_step({
Vic Yange7553162012-06-20 16:20:47 +08001084 'userspace_action': None if self.client_attr.keyboard_dev
Chun-ting Changd43aa9b2012-11-16 10:12:05 +08001085 else (self.faft_client.system.run_shell_command,
Tom Wai-Hong Tamc7ecfca2011-12-06 11:12:31 +08001086 'chromeos-firmwareupdate --mode tonormal && reboot'),
Vic Yange7553162012-06-20 16:20:47 +08001087 'reboot_action': self.disable_keyboard_dev_mode if
1088 self.client_attr.keyboard_dev else None,
Tom Wai-Hong Tamfd590c92011-11-25 11:50:57 +08001089 })
Tom Wai-Hong Tama9c1a502011-11-10 06:39:26 +08001090
1091
Tom Wai-Hong Tam4c153fa2013-01-22 13:56:06 +08001092 def setup_rw_boot(self, section='a'):
1093 """Make sure firmware is in RW-boot mode.
1094
1095 If the given firmware section is in RO-boot mode, turn off the RO-boot
1096 flag and reboot DUT into RW-boot mode.
1097
1098 Args:
1099 section: A firmware section, either 'a' or 'b'.
1100 """
1101 flags = self.faft_client.bios.get_preamble_flags(section)
1102 if flags & vboot.PREAMBLE_USE_RO_NORMAL:
1103 flags = flags ^ vboot.PREAMBLE_USE_RO_NORMAL
1104 self.run_faft_step({
1105 'userspace_action': (self.faft_client.bios.set_preamble_flags,
1106 (section, flags))
1107 })
1108
1109
Tom Wai-Hong Tamcfda61f2011-11-02 17:41:01 +08001110 def setup_kernel(self, part):
1111 """Setup for kernel test.
1112
1113 It makes sure both kernel A and B bootable and the current boot is
1114 the requested kernel part.
1115
1116 Args:
Tom Wai-Hong Tama9c1a502011-11-10 06:39:26 +08001117 part: A string of kernel partition number or 'a'/'b'.
Tom Wai-Hong Tamcfda61f2011-11-02 17:41:01 +08001118 """
1119 self.ensure_kernel_boot(part)
Chun-ting Changd43aa9b2012-11-16 10:12:05 +08001120 if self.faft_client.kernel.diff_a_b():
Tom Wai-Hong Tam622d0ba2012-08-15 16:29:05 +08001121 self.copy_kernel_and_rootfs(from_part=part,
1122 to_part=self.OTHER_KERNEL_MAP[part])
Tom Wai-Hong Tamcfda61f2011-11-02 17:41:01 +08001123 self.reset_and_prioritize_kernel(part)
1124
1125
1126 def reset_and_prioritize_kernel(self, part):
1127 """Make the requested partition highest priority.
1128
1129 This function also reset kerenl A and B to bootable.
1130
1131 Args:
Tom Wai-Hong Tama9c1a502011-11-10 06:39:26 +08001132 part: A string of partition number to be prioritized.
Tom Wai-Hong Tamcfda61f2011-11-02 17:41:01 +08001133 """
Chun-ting Changd43aa9b2012-11-16 10:12:05 +08001134 root_dev = self.faft_client.system.get_root_dev()
Tom Wai-Hong Tamcfda61f2011-11-02 17:41:01 +08001135 # Reset kernel A and B to bootable.
Chun-ting Changd43aa9b2012-11-16 10:12:05 +08001136 self.faft_client.system.run_shell_command(
1137 'cgpt add -i%s -P1 -S1 -T0 %s' % (self.KERNEL_MAP['a'], root_dev))
1138 self.faft_client.system.run_shell_command(
1139 'cgpt add -i%s -P1 -S1 -T0 %s' % (self.KERNEL_MAP['b'], root_dev))
Tom Wai-Hong Tamcfda61f2011-11-02 17:41:01 +08001140 # Set kernel part highest priority.
Chun-ting Changd43aa9b2012-11-16 10:12:05 +08001141 self.faft_client.system.run_shell_command('cgpt prioritize -i%s %s' %
Tom Wai-Hong Tamcfda61f2011-11-02 17:41:01 +08001142 (self.KERNEL_MAP[part], root_dev))
Tom Wai-Hong Tam6a863ba2011-12-08 10:13:28 +08001143 # Safer to sync and wait until the cgpt status written to the disk.
Chun-ting Changd43aa9b2012-11-16 10:12:05 +08001144 self.faft_client.system.run_shell_command('sync')
Tom Wai-Hong Tam41738762012-10-29 14:32:39 +08001145 time.sleep(self.delay.sync)
Tom Wai-Hong Tamcfda61f2011-11-02 17:41:01 +08001146
1147
Tom Wai-Hong Tam7ad99ab2012-07-30 19:30:51 +08001148 def warm_reboot(self):
1149 """Request a warm reboot.
1150
Tom Wai-Hong Tamb06f0802012-07-31 16:27:50 +08001151 A wrapper for underlying servo warm reset.
Tom Wai-Hong Tam7ad99ab2012-07-30 19:30:51 +08001152 """
Tom Wai-Hong Tamb06f0802012-07-31 16:27:50 +08001153 # Use cold reset if the warm reset is broken.
1154 if self.client_attr.broken_warm_reset:
Gediminas Ramanauskase021e152012-09-04 19:10:59 -07001155 logging.info('broken_warm_reset is True. Cold rebooting instead.')
1156 self.cold_reboot()
Tom Wai-Hong Tamb06f0802012-07-31 16:27:50 +08001157 else:
1158 self.servo.warm_reset()
Tom Wai-Hong Tam7ad99ab2012-07-30 19:30:51 +08001159
1160
1161 def cold_reboot(self):
1162 """Request a cold reboot.
1163
1164 A wrapper for underlying servo cold reset.
1165 """
Gediminas Ramanauskasc6025692012-10-23 14:33:40 -07001166 if self.client_attr.broken_warm_reset:
Tom Wai-Hong Tama276d0a2012-08-22 11:15:17 +08001167 self.servo.set('pwr_button', 'press')
1168 self.servo.set('cold_reset', 'on')
1169 self.servo.set('cold_reset', 'off')
Tom Wai-Hong Tam41738762012-10-29 14:32:39 +08001170 time.sleep(self.delay.ec_boot_to_pwr_button)
Tom Wai-Hong Tama276d0a2012-08-22 11:15:17 +08001171 self.servo.set('pwr_button', 'release')
Tom Wai-Hong Tam7ad99ab2012-07-30 19:30:51 +08001172 else:
1173 self.servo.cold_reset()
1174
1175
Tom Wai-Hong Tamb21b6b42012-07-26 10:46:30 +08001176 def sync_and_warm_reboot(self):
Tom Wai-Hong Tamf1e34972011-11-02 17:07:04 +08001177 """Request the client sync and do a warm reboot.
1178
1179 This is the default reboot action on FAFT.
1180 """
Chun-ting Changd43aa9b2012-11-16 10:12:05 +08001181 self.faft_client.system.run_shell_command('sync')
Tom Wai-Hong Tam41738762012-10-29 14:32:39 +08001182 time.sleep(self.delay.sync)
Tom Wai-Hong Tam7ad99ab2012-07-30 19:30:51 +08001183 self.warm_reboot()
Tom Wai-Hong Tamf1e34972011-11-02 17:07:04 +08001184
1185
Tom Wai-Hong Tamb21b6b42012-07-26 10:46:30 +08001186 def sync_and_cold_reboot(self):
1187 """Request the client sync and do a cold reboot.
1188
1189 This reboot action is used to reset EC for recovery mode.
1190 """
Chun-ting Changd43aa9b2012-11-16 10:12:05 +08001191 self.faft_client.system.run_shell_command('sync')
Tom Wai-Hong Tam41738762012-10-29 14:32:39 +08001192 time.sleep(self.delay.sync)
Tom Wai-Hong Tam7ad99ab2012-07-30 19:30:51 +08001193 self.cold_reboot()
Tom Wai-Hong Tamb21b6b42012-07-26 10:46:30 +08001194
1195
Tom Wai-Hong Tambb92e6c2012-10-30 11:06:09 +08001196 def sync_and_ec_reboot(self, flags=''):
Vic Yangaeb10392012-08-28 09:25:09 +08001197 """Request the client sync and do a EC triggered reboot.
1198
1199 Args:
Tom Wai-Hong Tambb92e6c2012-10-30 11:06:09 +08001200 flags: Optional, a space-separated string of flags passed to EC
1201 reboot command, including:
1202 default: EC soft reboot;
1203 'hard': EC cold/hard reboot.
Vic Yangaeb10392012-08-28 09:25:09 +08001204 """
Chun-ting Changd43aa9b2012-11-16 10:12:05 +08001205 self.faft_client.system.run_shell_command('sync')
Tom Wai-Hong Tam41738762012-10-29 14:32:39 +08001206 time.sleep(self.delay.sync)
Tom Wai-Hong Tambb92e6c2012-10-30 11:06:09 +08001207 self.ec.reboot(flags)
Tom Wai-Hong Tamad4aaae2012-12-12 11:02:06 +08001208 time.sleep(self.delay.ec_boot_to_console)
Vic Yangf86728a2012-07-30 10:44:07 +08001209 self.check_lid_and_power_on()
1210
1211
Tom Wai-Hong Tam3d00ab72012-11-14 10:39:22 +08001212 def reboot_with_factory_install_shim(self):
1213 """Request reboot with factory install shim to reset TPM.
Chun-ting Changa4f65532012-10-17 16:57:28 +08001214
Tom Wai-Hong Tam3d00ab72012-11-14 10:39:22 +08001215 Factory install shim requires dev mode enabled. So this method switches
1216 firmware to dev mode first and reboot. The client uses factory install
1217 shim to reset TPM values.
Chun-ting Changa4f65532012-10-17 16:57:28 +08001218 """
Tom Wai-Hong Tam3d00ab72012-11-14 10:39:22 +08001219 # Unplug USB first to avoid the complicated USB autoboot cases.
Vadim Bendeburye7bd9362012-12-19 14:35:20 -08001220 self.servo.switch_usbkey('host')
Vic Yangf93f7022012-10-31 09:40:36 +08001221 is_dev = self.checkers.crossystem_checker({'devsw_boot': '1'})
Chun-ting Changa4f65532012-10-17 16:57:28 +08001222 if not is_dev:
1223 self.enable_dev_mode_and_reboot()
Vic Yangf1fdf712012-10-31 12:09:22 +08001224 time.sleep(self.delay.sync)
Chun-ting Changa4f65532012-10-17 16:57:28 +08001225 self.enable_rec_mode_and_reboot()
Tom Wai-Hong Tam3d00ab72012-11-14 10:39:22 +08001226 self.wait_fw_screen_and_plug_usb()
Tom Wai-Hong Tam41738762012-10-29 14:32:39 +08001227 time.sleep(self.delay.install_shim_done)
Chun-ting Changa4f65532012-10-17 16:57:28 +08001228 self.warm_reboot()
1229
1230
Tom Wai-Hong Tamc8f2ca02012-09-14 11:18:01 +08001231 def full_power_off_and_on(self):
1232 """Shutdown the device by pressing power button and power on again."""
1233 # Press power button to trigger Chrome OS normal shutdown process.
Tom Wai-Hong Tambe464992012-12-12 10:54:07 +08001234 # We use a customized delay since the normal-press 1.2s is not enough.
1235 self.servo.power_key(self.delay.hold_pwr_button)
Tom Wai-Hong Tam41738762012-10-29 14:32:39 +08001236 time.sleep(self.delay.shutdown)
Tom Wai-Hong Tamc8f2ca02012-09-14 11:18:01 +08001237 # Short press power button to boot DUT again.
1238 self.servo.power_short_press()
1239
1240
Vic Yangf86728a2012-07-30 10:44:07 +08001241 def check_lid_and_power_on(self):
1242 """
1243 On devices with EC software sync, system powers on after EC reboots if
1244 lid is open. Otherwise, the EC shuts down CPU after about 3 seconds.
1245 This method checks lid switch state and presses power button if
1246 necessary.
1247 """
1248 if self.servo.get("lid_open") == "no":
Tom Wai-Hong Tam41738762012-10-29 14:32:39 +08001249 time.sleep(self.delay.software_sync)
Vic Yangf86728a2012-07-30 10:44:07 +08001250 self.servo.power_short_press()
Vic Yang59cac9c2012-05-21 15:28:42 +08001251
1252
Tom Wai-Hong Tam78709592011-12-19 11:16:50 +08001253 def _modify_usb_kernel(self, usb_dev, from_magic, to_magic):
1254 """Modify the kernel header magic in USB stick.
1255
1256 The kernel header magic is the first 8-byte of kernel partition.
1257 We modify it to make it fail on kernel verification check.
1258
1259 Args:
1260 usb_dev: A string of USB stick path on the host, like '/dev/sdc'.
1261 from_magic: A string of magic which we change it from.
1262 to_magic: A string of magic which we change it to.
1263
1264 Raises:
1265 error.TestError: if failed to change magic.
1266 """
1267 assert len(from_magic) == 8
1268 assert len(to_magic) == 8
Tom Wai-Hong Tama1d9a0f2011-12-23 09:13:33 +08001269 # USB image only contains one kernel.
1270 kernel_part = self._join_part(usb_dev, self.KERNEL_MAP['a'])
Tom Wai-Hong Tam78709592011-12-19 11:16:50 +08001271 read_cmd = "sudo dd if=%s bs=8 count=1 2>/dev/null" % kernel_part
1272 current_magic = utils.system_output(read_cmd)
1273 if current_magic == to_magic:
Vic Yang772df8a2012-10-31 10:10:49 +08001274 logging.info("The kernel magic is already %s.", current_magic)
Tom Wai-Hong Tam78709592011-12-19 11:16:50 +08001275 return
1276 if current_magic != from_magic:
1277 raise error.TestError("Invalid kernel image on USB: wrong magic.")
1278
Vic Yang772df8a2012-10-31 10:10:49 +08001279 logging.info('Modify the kernel magic in USB, from %s to %s.',
1280 from_magic, to_magic)
Tom Wai-Hong Tam78709592011-12-19 11:16:50 +08001281 write_cmd = ("echo -n '%s' | sudo dd of=%s oflag=sync conv=notrunc "
1282 " 2>/dev/null" % (to_magic, kernel_part))
1283 utils.system(write_cmd)
1284
1285 if utils.system_output(read_cmd) != to_magic:
1286 raise error.TestError("Failed to write new magic.")
1287
1288
1289 def corrupt_usb_kernel(self, usb_dev):
1290 """Corrupt USB kernel by modifying its magic from CHROMEOS to CORRUPTD.
1291
1292 Args:
1293 usb_dev: A string of USB stick path on the host, like '/dev/sdc'.
1294 """
1295 self._modify_usb_kernel(usb_dev, self.CHROMEOS_MAGIC,
1296 self.CORRUPTED_MAGIC)
1297
1298
1299 def restore_usb_kernel(self, usb_dev):
1300 """Restore USB kernel by modifying its magic from CORRUPTD to CHROMEOS.
1301
1302 Args:
1303 usb_dev: A string of USB stick path on the host, like '/dev/sdc'.
1304 """
1305 self._modify_usb_kernel(usb_dev, self.CORRUPTED_MAGIC,
1306 self.CHROMEOS_MAGIC)
1307
1308
Tom Wai-Hong Tamfc700b52012-09-13 21:33:52 +08001309 def _call_action(self, action_tuple, check_status=False):
Tom Wai-Hong Tama70f0fe2011-09-02 18:28:47 +08001310 """Call the action function with/without arguments.
1311
1312 Args:
Tom Wai-Hong Tamfc700b52012-09-13 21:33:52 +08001313 action_tuple: A function, or a tuple (function, args, error_msg),
1314 in which, args and error_msg are optional. args is
1315 either a value or a tuple if multiple arguments.
Vic Yang52116d42012-11-05 16:22:34 +08001316 This can also be a list containing multiple function
1317 or tuple. In this case, these actions are called in
1318 sequence.
Tom Wai-Hong Tamfc700b52012-09-13 21:33:52 +08001319 check_status: Check the return value of action function. If not
1320 succeed, raises a TestFail exception.
Tom Wai-Hong Tama70f0fe2011-09-02 18:28:47 +08001321
1322 Returns:
1323 The result value of the action function.
Tom Wai-Hong Tamfc700b52012-09-13 21:33:52 +08001324
1325 Raises:
1326 error.TestError: An error when the action function is not callable.
1327 error.TestFail: When check_status=True, action function not succeed.
Tom Wai-Hong Tama70f0fe2011-09-02 18:28:47 +08001328 """
Vic Yang52116d42012-11-05 16:22:34 +08001329 if isinstance(action_tuple, list):
1330 return all([self._call_action(action, check_status=check_status)
1331 for action in action_tuple])
1332
Tom Wai-Hong Tamfc700b52012-09-13 21:33:52 +08001333 action = action_tuple
1334 args = ()
1335 error_msg = 'Not succeed'
Tom Wai-Hong Tama70f0fe2011-09-02 18:28:47 +08001336 if isinstance(action_tuple, tuple):
1337 action = action_tuple[0]
Tom Wai-Hong Tamfc700b52012-09-13 21:33:52 +08001338 if len(action_tuple) >= 2:
1339 args = action_tuple[1]
1340 if not isinstance(args, tuple):
1341 args = (args,)
1342 if len(action_tuple) >= 3:
Tom Wai-Hong Tamff560882012-10-15 16:50:06 +08001343 error_msg = action_tuple[2]
Tom Wai-Hong Tama70f0fe2011-09-02 18:28:47 +08001344
Tom Wai-Hong Tamfc700b52012-09-13 21:33:52 +08001345 if action is None:
1346 return
1347
1348 if not callable(action):
1349 raise error.TestError('action is not callable!')
1350
1351 info_msg = 'calling %s' % str(action)
1352 if args:
1353 info_msg += ' with args %s' % str(args)
1354 logging.info(info_msg)
1355 ret = action(*args)
1356
1357 if check_status and not ret:
1358 raise error.TestFail('%s: %s returning %s' %
1359 (error_msg, info_msg, str(ret)))
1360 return ret
Tom Wai-Hong Tama70f0fe2011-09-02 18:28:47 +08001361
1362
Tom Wai-Hong Tam78709592011-12-19 11:16:50 +08001363 def run_shutdown_process(self, shutdown_action, pre_power_action=None,
Tom Wai-Hong Tam8da40de2012-12-12 12:15:54 +08001364 post_power_action=None, shutdown_timeout=None):
Tom Wai-Hong Tam78709592011-12-19 11:16:50 +08001365 """Run shutdown_action(), which makes DUT shutdown, and power it on.
1366
1367 Args:
1368 shutdown_action: a function which makes DUT shutdown, like pressing
1369 power key.
1370 pre_power_action: a function which is called before next power on.
1371 post_power_action: a function which is called after next power on.
Tom Wai-Hong Tam8da40de2012-12-12 12:15:54 +08001372 shutdown_timeout: a timeout to confirm DUT shutdown.
Tom Wai-Hong Tam78709592011-12-19 11:16:50 +08001373
1374 Raises:
1375 error.TestFail: if the shutdown_action() failed to turn DUT off.
1376 """
1377 self._call_action(shutdown_action)
1378 logging.info('Wait to ensure DUT shut down...')
1379 try:
Tom Wai-Hong Tam8da40de2012-12-12 12:15:54 +08001380 if shutdown_timeout is None:
1381 shutdown_timeout = self.delay.shutdown_timeout
1382 self.wait_for_client(timeout=shutdown_timeout)
Tom Wai-Hong Tam78709592011-12-19 11:16:50 +08001383 raise error.TestFail(
1384 'Should shut the device down after calling %s.' %
1385 str(shutdown_action))
1386 except AssertionError:
1387 logging.info(
1388 'DUT is surely shutdown. We are going to power it on again...')
1389
1390 if pre_power_action:
1391 self._call_action(pre_power_action)
Tom Wai-Hong Tam610262a2012-01-12 14:16:53 +08001392 self.servo.power_short_press()
Tom Wai-Hong Tam78709592011-12-19 11:16:50 +08001393 if post_power_action:
1394 self._call_action(post_power_action)
1395
1396
Tom Wai-Hong Tama70f0fe2011-09-02 18:28:47 +08001397 def register_faft_template(self, template):
1398 """Register FAFT template, the default FAFT_STEP of each step.
1399
Tom Wai-Hong Tam109f63c2011-12-08 14:58:27 +08001400 Any missing field falls back to the original faft_template.
1401
Tom Wai-Hong Tama70f0fe2011-09-02 18:28:47 +08001402 Args:
1403 template: A FAFT_STEP dict.
1404 """
Tom Wai-Hong Tam109f63c2011-12-08 14:58:27 +08001405 self._faft_template.update(template)
Tom Wai-Hong Tama70f0fe2011-09-02 18:28:47 +08001406
1407
1408 def register_faft_sequence(self, sequence):
1409 """Register FAFT sequence.
1410
1411 Args:
1412 sequence: A FAFT_SEQUENCE array which consisted of FAFT_STEP dicts.
1413 """
1414 self._faft_sequence = sequence
1415
1416
Tom Wai-Hong Tamc285f4c2012-10-30 15:44:39 +08001417 def run_faft_step(self, step, no_reboot=False, next_step=None):
Tom Wai-Hong Tam2c50dff2011-11-11 07:01:01 +08001418 """Run a single FAFT step.
1419
1420 Any missing field falls back to faft_template. An empty step means
1421 running the default faft_template.
1422
1423 Args:
1424 step: A FAFT_STEP dict.
1425 no_reboot: True to prevent running reboot_action and firmware_action.
Tom Wai-Hong Tamc285f4c2012-10-30 15:44:39 +08001426 next_step: Optional, a FAFT_STEP dict of the next step, which is used
1427 for diagnostic.
Tom Wai-Hong Tama70f0fe2011-09-02 18:28:47 +08001428
1429 Raises:
Tom Wai-Hong Tamd8445dc2011-12-15 09:00:04 +08001430 error.TestError: An error when the given step is not valid.
Tom Wai-Hong Tam4bb85e22012-10-25 14:35:24 +08001431 error.TestFail: Test failed in waiting DUT reboot.
Tom Wai-Hong Tama70f0fe2011-09-02 18:28:47 +08001432 """
Tom Wai-Hong Tamd8445dc2011-12-15 09:00:04 +08001433 FAFT_STEP_KEYS = ('state_checker', 'userspace_action', 'reboot_action',
1434 'firmware_action', 'install_deps_after_boot')
1435
Tom Wai-Hong Tam2c50dff2011-11-11 07:01:01 +08001436 test = {}
1437 test.update(self._faft_template)
1438 test.update(step)
1439
Tom Wai-Hong Tamd8445dc2011-12-15 09:00:04 +08001440 for key in test:
1441 if key not in FAFT_STEP_KEYS:
Tom Wai-Hong Tam78709592011-12-19 11:16:50 +08001442 raise error.TestError('Invalid key in FAFT step: %s', key)
Tom Wai-Hong Tamd8445dc2011-12-15 09:00:04 +08001443
Tom Wai-Hong Tam2c50dff2011-11-11 07:01:01 +08001444 if test['state_checker']:
Tom Wai-Hong Tamfc700b52012-09-13 21:33:52 +08001445 self._call_action(test['state_checker'], check_status=True)
Tom Wai-Hong Tam2c50dff2011-11-11 07:01:01 +08001446
1447 self._call_action(test['userspace_action'])
1448
1449 # Don't run reboot_action and firmware_action if no_reboot is True.
1450 if not no_reboot:
1451 self._call_action(test['reboot_action'])
1452 self.wait_for_client_offline()
1453 self._call_action(test['firmware_action'])
1454
Vic Yang8eaf5ad2012-09-13 14:05:37 +08001455 try:
1456 if 'install_deps_after_boot' in test:
1457 self.wait_for_client(
1458 install_deps=test['install_deps_after_boot'])
1459 else:
1460 self.wait_for_client()
1461 except AssertionError:
Yusuf Mohsinally928f8c72012-12-11 15:27:02 -08001462 logging.error('wait_for_client() timed out.')
Tom Wai-Hong Tamc285f4c2012-10-30 15:44:39 +08001463 self._restore_routine_from_timeout(next_step)
Tom Wai-Hong Tam2c50dff2011-11-11 07:01:01 +08001464
1465
1466 def run_faft_sequence(self):
1467 """Run FAFT sequence which was previously registered."""
Tom Wai-Hong Tama70f0fe2011-09-02 18:28:47 +08001468 sequence = self._faft_sequence
Tom Wai-Hong Tamc285f4c2012-10-30 15:44:39 +08001469 for index, step in enumerate(sequence):
Vic Yang772df8a2012-10-31 10:10:49 +08001470 logging.info('======== Running FAFT sequence step %d ========',
Tom Wai-Hong Tamc285f4c2012-10-30 15:44:39 +08001471 index + 1)
Tom Wai-Hong Tam2c50dff2011-11-11 07:01:01 +08001472 # Don't reboot in the last step.
Tom Wai-Hong Tamc285f4c2012-10-30 15:44:39 +08001473 if index == len(sequence) - 1:
1474 self.run_faft_step(step, no_reboot=True)
1475 else:
1476 self.run_faft_step(step, next_step=sequence[index + 1])
ctchang38ae4922012-09-03 17:01:16 +08001477
1478
ctchang38ae4922012-09-03 17:01:16 +08001479 def get_current_firmware_sha(self):
1480 """Get current firmware sha of body and vblock.
1481
1482 Returns:
1483 Current firmware sha follows the order (
1484 vblock_a_sha, body_a_sha, vblock_b_sha, body_b_sha)
1485 """
Chun-ting Changd43aa9b2012-11-16 10:12:05 +08001486 current_firmware_sha = (self.faft_client.bios.get_sig_sha('a'),
1487 self.faft_client.bios.get_body_sha('a'),
1488 self.faft_client.bios.get_sig_sha('b'),
1489 self.faft_client.bios.get_body_sha('b'))
ctchang38ae4922012-09-03 17:01:16 +08001490 return current_firmware_sha
1491
1492
Tom Wai-Hong Tame6232342012-09-24 16:18:01 +08001493 def is_firmware_changed(self):
1494 """Check if the current firmware changed, by comparing its SHA.
ctchang38ae4922012-09-03 17:01:16 +08001495
1496 Returns:
Tom Wai-Hong Tame6232342012-09-24 16:18:01 +08001497 True if it is changed, otherwise Flase.
ctchang38ae4922012-09-03 17:01:16 +08001498 """
Tom Wai-Hong Tame6232342012-09-24 16:18:01 +08001499 # Device may not be rebooted after test.
Chun-ting Changd43aa9b2012-11-16 10:12:05 +08001500 self.faft_client.bios.reload()
ctchang38ae4922012-09-03 17:01:16 +08001501
1502 current_sha = self.get_current_firmware_sha()
1503
1504 if current_sha == self._backup_firmware_sha:
Tom Wai-Hong Tame6232342012-09-24 16:18:01 +08001505 return False
ctchang38ae4922012-09-03 17:01:16 +08001506 else:
ctchang38ae4922012-09-03 17:01:16 +08001507 corrupt_VBOOTA = (current_sha[0] != self._backup_firmware_sha[0])
1508 corrupt_FVMAIN = (current_sha[1] != self._backup_firmware_sha[1])
1509 corrupt_VBOOTB = (current_sha[2] != self._backup_firmware_sha[2])
1510 corrupt_FVMAINB = (current_sha[3] != self._backup_firmware_sha[3])
Tom Wai-Hong Tame6232342012-09-24 16:18:01 +08001511 logging.info("Firmware changed:")
Vic Yang772df8a2012-10-31 10:10:49 +08001512 logging.info('VBOOTA is changed: %s', corrupt_VBOOTA)
1513 logging.info('VBOOTB is changed: %s', corrupt_VBOOTB)
1514 logging.info('FVMAIN is changed: %s', corrupt_FVMAIN)
1515 logging.info('FVMAINB is changed: %s', corrupt_FVMAINB)
Tom Wai-Hong Tame6232342012-09-24 16:18:01 +08001516 return True
ctchang38ae4922012-09-03 17:01:16 +08001517
1518
1519 def backup_firmware(self, suffix='.original'):
1520 """Backup firmware to file, and then send it to host.
1521
1522 Args:
1523 suffix: a string appended to backup file name
1524 """
Chun-ting Changd43aa9b2012-11-16 10:12:05 +08001525 remote_temp_dir = self.faft_client.system.create_temp_dir()
1526 self.faft_client.bios.dump_whole(os.path.join(remote_temp_dir, 'bios'))
Chun-ting Chang9380c2c2012-10-05 17:31:05 +08001527 self._client.get_file(os.path.join(remote_temp_dir, 'bios'),
1528 os.path.join(self.resultsdir, 'bios' + suffix))
ctchang38ae4922012-09-03 17:01:16 +08001529
1530 self._backup_firmware_sha = self.get_current_firmware_sha()
Vic Yang772df8a2012-10-31 10:10:49 +08001531 logging.info('Backup firmware stored in %s with suffix %s',
1532 self.resultsdir, suffix)
ctchang38ae4922012-09-03 17:01:16 +08001533
1534
Tom Wai-Hong Tame6232342012-09-24 16:18:01 +08001535 def is_firmware_saved(self):
1536 """Check if a firmware saved (called backup_firmware before).
1537
1538 Returns:
1539 True if the firmware is backuped; otherwise False.
1540 """
1541 return self._backup_firmware_sha != ()
1542
1543
Tom Wai-Hong Tam1dd11592012-10-26 15:01:45 +08001544 def clear_saved_firmware(self):
1545 """Clear the firmware saved by the method backup_firmware."""
1546 self._backup_firmware_sha = ()
1547
1548
ctchang38ae4922012-09-03 17:01:16 +08001549 def restore_firmware(self, suffix='.original'):
1550 """Restore firmware from host in resultsdir.
1551
1552 Args:
1553 suffix: a string appended to backup file name
1554 """
Tom Wai-Hong Tame6232342012-09-24 16:18:01 +08001555 if not self.is_firmware_changed():
ctchang38ae4922012-09-03 17:01:16 +08001556 return
1557
1558 # Backup current corrupted firmware.
1559 self.backup_firmware(suffix='.corrupt')
1560
1561 # Restore firmware.
Chun-ting Changd43aa9b2012-11-16 10:12:05 +08001562 remote_temp_dir = self.faft_client.system.create_temp_dir()
Chun-ting Chang9380c2c2012-10-05 17:31:05 +08001563 self._client.send_file(os.path.join(self.resultsdir, 'bios' + suffix),
1564 os.path.join(remote_temp_dir, 'bios'))
ctchang38ae4922012-09-03 17:01:16 +08001565
Chun-ting Changd43aa9b2012-11-16 10:12:05 +08001566 self.faft_client.bios.write_whole(
1567 os.path.join(remote_temp_dir, 'bios'))
Tom Wai-Hong Tame6232342012-09-24 16:18:01 +08001568 self.sync_and_warm_reboot()
1569 self.wait_for_client_offline()
Tom Wai-Hong Tame2f9cf92012-11-26 10:04:11 +08001570 self.wait_dev_screen_and_ctrl_d()
Tom Wai-Hong Tame6232342012-09-24 16:18:01 +08001571 self.wait_for_client()
1572
ctchang38ae4922012-09-03 17:01:16 +08001573 logging.info('Successfully restore firmware.')
Chun-ting Changf91ee0f2012-09-17 18:31:54 +08001574
1575
1576 def setup_firmwareupdate_shellball(self, shellball=None):
1577 """Deside a shellball to use in firmware update test.
1578
1579 Check if there is a given shellball, and it is a shell script. Then,
1580 send it to the remote host. Otherwise, use
1581 /usr/sbin/chromeos-firmwareupdate.
1582
1583 Args:
1584 shellball: path of a shellball or default to None.
1585
1586 Returns:
1587 Path of shellball in remote host.
1588 If use default shellball, reutrn None.
1589 """
1590 updater_path = None
1591 if shellball:
1592 # Determine the firmware file is a shellball or a raw binary.
1593 is_shellball = (utils.system_output("file %s" % shellball).find(
1594 "shell script") != -1)
1595 if is_shellball:
Vic Yang772df8a2012-10-31 10:10:49 +08001596 logging.info('Device will update firmware with shellball %s',
1597 shellball)
Chun-ting Changd43aa9b2012-11-16 10:12:05 +08001598 temp_dir = self.faft_client.system.create_temp_dir(
1599 'shellball_')
Chun-ting Changf91ee0f2012-09-17 18:31:54 +08001600 temp_shellball = os.path.join(temp_dir, 'updater.sh')
1601 self._client.send_file(shellball, temp_shellball)
1602 updater_path = temp_shellball
1603 else:
1604 raise error.TestFail(
1605 'The given shellball is not a shell script.')
1606 return updater_path