blob: f202cb63bbc8412b7176da88d28c57ae035f6d8e [file] [log] [blame]
Tom Wai-Hong Tamc1e0b9a2012-11-01 13:52:39 +08001#!/usr/bin/python -u
barfab@chromium.orgb6d29932012-04-11 09:46:43 +02002# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -07003# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6"""Exposes the FAFTClient interface over XMLRPC.
7
8It launches a XMLRPC server and exposes the interface of FAFTClient object.
9The FAFTClient object aggreates some useful functions of exisintg SAFT
10libraries.
11"""
12
ctchang38ae4922012-09-03 17:01:16 +080013import functools, os, shutil, sys, tempfile
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -070014from optparse import OptionParser
15from SimpleXMLRPCServer import SimpleXMLRPCServer
16
Tom Wai-Hong Tamc0168912012-09-13 13:24:02 +080017from saft import cgpt_state, chromeos_interface, flashrom_handler
18from saft import kernel_handler, saft_flashrom_util, tpm_handler
Chun-ting Changcf924e92012-10-29 13:49:01 +080019from firmware_updater import FirmwareUpdater
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -070020
21
Tom Wai-Hong Tam0e680af2011-10-26 14:32:55 +080022def allow_multiple_section_input(image_operator):
23 @functools.wraps(image_operator)
24 def wrapper(self, section):
25 if type(section) in (tuple, list):
26 for sec in section:
27 image_operator(self, sec)
28 else:
29 image_operator(self, section)
30 return wrapper
31
32
Vic Yang13d22ec2012-06-18 15:12:47 +080033class LazyFlashromHandlerProxy:
34 _loaded = False
35 _obj = None
36
37 def __init__(self, *args, **kargs):
38 self._args = args
39 self._kargs = kargs
40
41 def _load(self):
42 self._obj = flashrom_handler.FlashromHandler()
43 self._obj.init(*self._args, **self._kargs)
44 self._obj.new_image()
45 self._loaded = True
46
47 def __getattr__(self, name):
48 if not self._loaded:
49 self._load()
50 return getattr(self._obj, name)
51
Tom Wai-Hong Tamc1c4deb2012-07-26 14:28:11 +080052 def reload(self):
53 self._loaded = False
54
Vic Yang13d22ec2012-06-18 15:12:47 +080055
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -070056class FAFTClient(object):
57 """A class of FAFT client which aggregates some useful functions of SAFT.
58
59 This class can be exposed via a XMLRPC server such that its functions can
60 be accessed remotely.
61
62 Attributes:
63 _chromeos_interface: An object to encapsulate OS services functions.
Vic Yang59cac9c2012-05-21 15:28:42 +080064 _bios_handler: An object to automate BIOS flashrom testing.
65 _ec_handler: An object to automate EC flashrom testing.
Tom Wai-Hong Tam23870e02012-08-24 16:15:34 +080066 _ec_image: An object to automate EC image for autest.
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -070067 _kernel_handler: An object to provide kernel related actions.
68 _tpm_handler: An object to control TPM device.
Chun-ting Changcf924e92012-10-29 13:49:01 +080069 _updater: An object to update firmware.
ctchangc7e55ea2012-08-09 16:19:14 +080070 _temp_path: Path of a temp directory.
71 _keys_path: Path of a directory, keys/, in temp directory.
72 _work_path: Path of a directory, work/, in temp directory.
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -070073 """
74
75 def __init__(self):
76 """Initialize the data attributes of this class."""
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -070077 # TODO(waihong): Move the explicit object.init() methods to the
78 # objects' constructors (ChromeOSInterface, FlashromHandler,
79 # KernelHandler, and TpmHandler).
80 self._chromeos_interface = chromeos_interface.ChromeOSInterface(False)
Tom Wai-Hong Tam48958832011-12-30 10:16:57 +080081 # We keep the state of FAFT test in a permanent directory over reboots.
Tom Wai-Hong Tam07278c22012-02-08 16:53:00 +080082 state_dir = '/var/tmp/faft'
83 self._chromeos_interface.init(state_dir, log_file='/tmp/faft_log.txt')
84 os.chdir(state_dir)
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -070085
Vic Yang13d22ec2012-06-18 15:12:47 +080086 self._bios_handler = LazyFlashromHandlerProxy(
87 saft_flashrom_util,
Vic Yang59cac9c2012-05-21 15:28:42 +080088 self._chromeos_interface,
89 None,
90 '/usr/share/vboot/devkeys',
91 'bios')
Vic Yang59cac9c2012-05-21 15:28:42 +080092
Todd Brochf2b1d012012-06-14 12:55:21 -070093 self._ec_handler = None
94 if not os.system("mosys ec info"):
Vic Yang13d22ec2012-06-18 15:12:47 +080095 self._ec_handler = LazyFlashromHandlerProxy(
96 saft_flashrom_util,
Todd Brochf2b1d012012-06-14 12:55:21 -070097 self._chromeos_interface,
Vic Yang13d22ec2012-06-18 15:12:47 +080098 'ec_root_key.vpubk',
Todd Brochf2b1d012012-06-14 12:55:21 -070099 '/usr/share/vboot/devkeys',
100 'ec')
Todd Brochf2b1d012012-06-14 12:55:21 -0700101
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700102
103 self._kernel_handler = kernel_handler.KernelHandler()
Tom Wai-Hong Tam07278c22012-02-08 16:53:00 +0800104 # TODO(waihong): The dev_key_path is a new argument. We do that in
105 # order not to break the old image and still be able to run.
106 try:
107 self._kernel_handler.init(self._chromeos_interface,
ctchangd60030f2012-08-29 15:39:56 +0800108 dev_key_path='/usr/share/vboot/devkeys',
109 internal_disk=True)
Tom Wai-Hong Tam07278c22012-02-08 16:53:00 +0800110 except:
111 # Copy the key to the current working directory.
112 shutil.copy('/usr/share/vboot/devkeys/kernel_data_key.vbprivk', '.')
ctchangd60030f2012-08-29 15:39:56 +0800113 self._kernel_handler.init(self._chromeos_interface,
114 internal_disk=True)
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700115
116 self._tpm_handler = tpm_handler.TpmHandler()
117 self._tpm_handler.init(self._chromeos_interface)
118
Tom Wai-Hong Tam48958832011-12-30 10:16:57 +0800119 self._cgpt_state = cgpt_state.CgptState(
Tom Wai-Hong Tamed2231c2012-07-27 14:39:46 +0800120 'SHORT', self._chromeos_interface, self.get_root_dev())
Tom Wai-Hong Tam48958832011-12-30 10:16:57 +0800121
Chun-ting Changcf924e92012-10-29 13:49:01 +0800122 self._updater = FirmwareUpdater(self._chromeos_interface)
123
124
ctchangc7e55ea2012-08-09 16:19:14 +0800125 # Initialize temporary directory path
126 self._temp_path = '/var/tmp/faft/autest'
127 self._keys_path = os.path.join(self._temp_path, 'keys')
128 self._work_path = os.path.join(self._temp_path, 'work')
129
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700130
Tom Wai-Hong Tame8f291a2011-12-08 22:03:53 +0800131 def _dispatch(self, method, params):
132 """This _dispatch method handles string conversion especially.
133
134 Since we turn off allow_dotted_names option. So any string conversion,
135 like str(FAFTClient.method), i.e. FAFTClient.method.__str__, failed
136 via XML RPC call.
137 """
138 is_str = method.endswith('.__str__')
139 if is_str:
140 method = method.rsplit('.', 1)[0]
141 try:
142 func = getattr(self, method)
143 except AttributeError:
144 raise Exception('method "%s" is not supported' % method)
145 else:
146 if is_str:
147 return str(func)
148 else:
149 return func(*params)
150
151
Tom Wai-Hong Tambea57b32011-09-02 18:27:47 +0800152 def is_available(self):
153 """Function for polling the RPC server availability.
154
155 Returns:
156 Always True.
157 """
158 return True
159
160
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700161 def run_shell_command(self, command):
162 """Run shell command.
163
164 Args:
165 command: A shell command to be run.
166 """
167 self._chromeos_interface.log('Requesting run shell command')
168 self._chromeos_interface.run_shell_command(command)
169
170
171 def run_shell_command_get_output(self, command):
172 """Run shell command and get its console output.
173
174 Args:
175 command: A shell command to be run.
176
177 Returns:
178 A list of strings stripped of the newline characters.
179 """
180 self._chromeos_interface.log(
181 'Requesting run shell command and get its console output')
182 return self._chromeos_interface.run_shell_command_get_output(command)
183
184
185 def software_reboot(self):
186 """Request software reboot."""
187 self._chromeos_interface.log('Requesting software reboot')
188 self._chromeos_interface.run_shell_command('reboot')
189
190
Tom Wai-Hong Tam678ab152011-12-14 15:27:24 +0800191 def get_platform_name(self):
192 """Get the platform name of the current system.
193
194 Returns:
195 A string of the platform name.
196 """
197 self._chromeos_interface.log('Requesting get platform name')
Vic Yang2bbb8672012-11-12 12:14:53 +0800198 # 'mosys platform name' sometimes fails. Let's get the verbose output.
199 lines = self._chromeos_interface.run_shell_command_get_output(
200 '(mosys -vvv platform name 2>&1) || echo Failed')
201 if lines[-1].strip() == 'Failed':
202 raise Exception('Failed getting platform name: ' + '\n'.join(lines))
203 return lines[-1]
Tom Wai-Hong Tam678ab152011-12-14 15:27:24 +0800204
205
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700206 def get_crossystem_value(self, key):
207 """Get crossystem value of the requested key.
208
209 Args:
210 key: A crossystem key.
211
212 Returns:
213 A string of the requested crossystem value.
214 """
215 self._chromeos_interface.log('Requesting get crossystem value')
216 return self._chromeos_interface.run_shell_command_get_output(
217 'crossystem %s' % key)[0]
218
219
Tom Wai-Hong Tamcfda61f2011-11-02 17:41:01 +0800220 def get_root_dev(self):
221 """Get the name of root device without partition number.
222
223 Returns:
224 A string of the root device without partition number.
225 """
226 self._chromeos_interface.log('Requesting get root device')
227 return self._chromeos_interface.get_root_dev()
228
229
230 def get_root_part(self):
231 """Get the name of root device with partition number.
232
233 Returns:
234 A string of the root device with partition number.
235 """
236 self._chromeos_interface.log('Requesting get root part')
237 return self._chromeos_interface.get_root_part()
238
239
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700240 def set_try_fw_b(self):
241 """Set 'Try Frimware B' flag in crossystem."""
242 self._chromeos_interface.log('Requesting restart with firmware B')
243 self._chromeos_interface.cs.fwb_tries = 1
244
245
Tom Wai-Hong Tam76c75072011-10-25 18:00:12 +0800246 def request_recovery_boot(self):
247 """Request running in recovery mode on the restart."""
248 self._chromeos_interface.log('Requesting restart in recovery mode')
249 self._chromeos_interface.cs.request_recovery()
250
251
Tom Wai-Hong Tam0a7b2be2012-10-15 16:44:12 +0800252 def get_dev_boot_usb(self):
253 """Get dev_boot_usb value which controls developer mode boot from USB.
254
255 Returns:
256 True if enable, False if disable.
257 """
258 self._chromeos_interface.log('Getting dev_boot_usb')
259 return self._chromeos_interface.cs.dev_boot_usb == '1'
260
261
262 def set_dev_boot_usb(self, value):
263 """Set dev_boot_usb value which controls developer mode boot from USB.
264
265 Args:
266 value: True to enable, False to disable.
267 """
268 self._chromeos_interface.log('Setting dev_boot_usb to %s' % str(value))
269 self._chromeos_interface.cs.dev_boot_usb = 1 if value else 0
270
271
Tom Wai-Hong Tam8c9eed62011-12-28 15:05:05 +0800272 def get_gbb_flags(self):
273 """Get the GBB flags.
274
275 Returns:
276 An integer of the GBB flags.
277 """
278 self._chromeos_interface.log('Getting GBB flags')
Vic Yang59cac9c2012-05-21 15:28:42 +0800279 return self._bios_handler.get_gbb_flags()
Tom Wai-Hong Tam8c9eed62011-12-28 15:05:05 +0800280
281
Tom Wai-Hong Tam81f70002011-12-13 12:29:46 +0800282 def get_firmware_flags(self, section):
283 """Get the preamble flags of a firmware section.
284
285 Args:
286 section: A firmware section, either 'a' or 'b'.
287
288 Returns:
289 An integer of the preamble flags.
290 """
291 self._chromeos_interface.log('Getting preamble flags of firmware %s' %
292 section)
Vic Yang59cac9c2012-05-21 15:28:42 +0800293 return self._bios_handler.get_section_flags(section)
294
295
Vic Yang91b73cf2012-07-31 17:18:11 +0800296 def set_firmware_flags(self, section, flags):
297 """Set the preamble flags of a firmware section.
298
299 Args:
300 section: A firmware section, either 'a' or 'b'.
301 flags: An integer of preamble flags.
302 """
303 self._chromeos_interface.log(
304 'Setting preamble flags of firmware %s to %s' % (section, flags))
305 version = self.get_firmware_version(section)
306 self._bios_handler.set_section_version(section, version, flags,
307 write_through=True)
308
309
Tom Wai-Hong Tam4e10b9f2012-09-06 16:23:02 +0800310 def get_firmware_sha(self, section):
311 """Get SHA1 hash of BIOS RW firmware section.
312
313 Args:
314 section: A firmware section, either 'a' or 'b'.
315 flags: An integer of preamble flags.
316 """
317 return self._bios_handler.get_section_sha(section)
318
319
ctchang38ae4922012-09-03 17:01:16 +0800320 def get_firmware_sig_sha(self, section):
321 """Get SHA1 hash of firmware vblock in section."""
322 return self._bios_handler.get_section_sig_sha(section)
323
324
Vic Yang91b73cf2012-07-31 17:18:11 +0800325 def get_EC_firmware_sha(self):
Tom Wai-Hong Tam4e10b9f2012-09-06 16:23:02 +0800326 """Get SHA1 hash of EC RW firmware section."""
Vic Yang91b73cf2012-07-31 17:18:11 +0800327 return self._ec_handler.get_section_sha('rw')
328
329
Tom Wai-Hong Tamc1c4deb2012-07-26 14:28:11 +0800330 def reload_firmware(self):
331 """Reload the firmware image that may be changed."""
332 self._bios_handler.reload()
333
334
Vic Yang59cac9c2012-05-21 15:28:42 +0800335 @allow_multiple_section_input
336 def corrupt_EC(self, section):
337 """Corrupt the requested EC section signature.
338
339 Args:
340 section: A EC section, either 'a' or 'b'.
341 """
342 self._chromeos_interface.log('Corrupting EC signature %s' %
343 section)
Vic Yang37a55462012-06-29 14:00:28 +0800344 self._ec_handler.corrupt_firmware(section, corrupt_all=True)
Vic Yang59cac9c2012-05-21 15:28:42 +0800345
346
347 @allow_multiple_section_input
348 def corrupt_EC_body(self, section):
349 """Corrupt the requested EC section body.
350
351 Args:
352 section: An EC section, either 'a' or 'b'.
353 """
354 self._chromeos_interface.log('Corrupting EC body %s' %
355 section)
Vic Yang37a55462012-06-29 14:00:28 +0800356 self._ec_handler.corrupt_firmware_body(section, corrupt_all=True)
Vic Yang59cac9c2012-05-21 15:28:42 +0800357
358
359 @allow_multiple_section_input
360 def restore_EC(self, section):
361 """Restore the previously corrupted EC section signature.
362
363 Args:
364 section: An EC section, either 'a' or 'b'.
365 """
366 self._chromeos_interface.log('Restoring EC signature %s' %
367 section)
Vic Yang37a55462012-06-29 14:00:28 +0800368 self._ec_handler.restore_firmware(section, restore_all=True)
Vic Yang59cac9c2012-05-21 15:28:42 +0800369
370
371 @allow_multiple_section_input
372 def restore_EC_body(self, section):
373 """Restore the previously corrupted EC section body.
374
375 Args:
376 section: An EC section, either 'a' or 'b'.
377 """
378 self._chromeos_interface.log('Restoring EC body %s' %
379 section)
Vic Yang37a55462012-06-29 14:00:28 +0800380 self._ec_handler.restore_firmware_body(section, restore_all=True)
Tom Wai-Hong Tam81f70002011-12-13 12:29:46 +0800381
382
Tom Wai-Hong Tam0e680af2011-10-26 14:32:55 +0800383 @allow_multiple_section_input
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700384 def corrupt_firmware(self, section):
Tom Wai-Hong Tam9aea8212011-12-12 15:08:45 +0800385 """Corrupt the requested firmware section signature.
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700386
387 Args:
388 section: A firmware section, either 'a' or 'b'.
389 """
Tom Wai-Hong Tam9aea8212011-12-12 15:08:45 +0800390 self._chromeos_interface.log('Corrupting firmware signature %s' %
391 section)
Vic Yang59cac9c2012-05-21 15:28:42 +0800392 self._bios_handler.corrupt_firmware(section)
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700393
394
Tom Wai-Hong Tam0e680af2011-10-26 14:32:55 +0800395 @allow_multiple_section_input
Tom Wai-Hong Tam81f70002011-12-13 12:29:46 +0800396 def corrupt_firmware_body(self, section):
397 """Corrupt the requested firmware section body.
398
399 Args:
400 section: A firmware section, either 'a' or 'b'.
401 """
402 self._chromeos_interface.log('Corrupting firmware body %s' %
403 section)
Vic Yang59cac9c2012-05-21 15:28:42 +0800404 self._bios_handler.corrupt_firmware_body(section)
Tom Wai-Hong Tam81f70002011-12-13 12:29:46 +0800405
406
407 @allow_multiple_section_input
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700408 def restore_firmware(self, section):
Tom Wai-Hong Tam9aea8212011-12-12 15:08:45 +0800409 """Restore the previously corrupted firmware section signature.
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700410
411 Args:
412 section: A firmware section, either 'a' or 'b'.
413 """
Tom Wai-Hong Tam9aea8212011-12-12 15:08:45 +0800414 self._chromeos_interface.log('Restoring firmware signature %s' %
415 section)
Vic Yang59cac9c2012-05-21 15:28:42 +0800416 self._bios_handler.restore_firmware(section)
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700417
418
Tom Wai-Hong Tamcfda61f2011-11-02 17:41:01 +0800419 @allow_multiple_section_input
Tom Wai-Hong Tam81f70002011-12-13 12:29:46 +0800420 def restore_firmware_body(self, section):
421 """Restore the previously corrupted firmware section body.
422
423 Args:
424 section: A firmware section, either 'a' or 'b'.
425 """
426 self._chromeos_interface.log('Restoring firmware body %s' %
427 section)
Vic Yang59cac9c2012-05-21 15:28:42 +0800428 self._bios_handler.restore_firmware_body(section)
Tom Wai-Hong Tam81f70002011-12-13 12:29:46 +0800429
430
Vic Yang91b73cf2012-07-31 17:18:11 +0800431 def get_firmware_version(self, section):
432 """Retrieve firmware version of a section."""
433 return self._bios_handler.get_section_version(section)
434
435
Chun-ting Changa4f65532012-10-17 16:57:28 +0800436 def get_tpm_firmware_version(self):
437 """Retrieve tpm firmware body version."""
438 return self._tpm_handler.get_fw_version()
439
440
Tom Wai-Hong Tam46d03b12012-02-08 12:02:17 +0800441 def _modify_firmware_version(self, section, delta):
442 """Modify firmware version for the requested section, by adding delta.
443
444 The passed in delta, a positive or a negative number, is added to the
445 original firmware version.
446 """
Vic Yang91b73cf2012-07-31 17:18:11 +0800447 original_version = self.get_firmware_version(section)
Tom Wai-Hong Tam46d03b12012-02-08 12:02:17 +0800448 new_version = original_version + delta
Vic Yang59cac9c2012-05-21 15:28:42 +0800449 flags = self._bios_handler.get_section_flags(section)
Tom Wai-Hong Tam46d03b12012-02-08 12:02:17 +0800450 self._chromeos_interface.log(
451 'Setting firmware section %s version from %d to %d' % (
452 section, original_version, new_version))
Vic Yang59cac9c2012-05-21 15:28:42 +0800453 self._bios_handler.set_section_version(section, new_version, flags,
454 write_through=True)
Tom Wai-Hong Tam46d03b12012-02-08 12:02:17 +0800455
456 @allow_multiple_section_input
457 def move_firmware_backward(self, section):
458 """Decrement firmware version for the requested section."""
459 self._modify_firmware_version(section, -1)
460
461
462 @allow_multiple_section_input
463 def move_firmware_forward(self, section):
464 """Increase firmware version for the requested section."""
465 self._modify_firmware_version(section, 1)
466
Chun-ting Changa4f65532012-10-17 16:57:28 +0800467 def get_firmware_datakey_version(self, section):
ctchangc7e55ea2012-08-09 16:19:14 +0800468 """Return firmware data key version."""
469 return self._bios_handler.get_section_datakey_version(section)
470
Chun-ting Changa4f65532012-10-17 16:57:28 +0800471 def get_tpm_firmware_datakey_version(self):
472 """Retrieve tpm firmware data key version."""
473 return self._tpm_handler.get_fw_body_version()
474
ctchangc7e55ea2012-08-09 16:19:14 +0800475 def retrieve_kernel_subkey_version(self,section):
476 """Return kernel subkey version."""
477 return self._bios_handler.get_section_kernel_subkey_version(section)
Tom Wai-Hong Tam46d03b12012-02-08 12:02:17 +0800478
Tom Wai-Hong Tam81f70002011-12-13 12:29:46 +0800479 @allow_multiple_section_input
Tom Wai-Hong Tamcfda61f2011-11-02 17:41:01 +0800480 def corrupt_kernel(self, section):
481 """Corrupt the requested kernel section.
482
483 Args:
484 section: A kernel section, either 'a' or 'b'.
485 """
486 self._chromeos_interface.log('Corrupting kernel %s' % section)
487 self._kernel_handler.corrupt_kernel(section)
488
489
490 @allow_multiple_section_input
491 def restore_kernel(self, section):
492 """Restore the requested kernel section (previously corrupted).
493
494 Args:
495 section: A kernel section, either 'a' or 'b'.
496 """
Tom Wai-Hong Tamcfda61f2011-11-02 17:41:01 +0800497 self._kernel_handler.restore_kernel(section)
498
499
Tom Wai-Hong Tam07278c22012-02-08 16:53:00 +0800500 def _modify_kernel_version(self, section, delta):
501 """Modify kernel version for the requested section, by adding delta.
502
503 The passed in delta, a positive or a negative number, is added to the
504 original kernel version.
505 """
506 original_version = self._kernel_handler.get_version(section)
507 new_version = original_version + delta
508 self._chromeos_interface.log(
509 'Setting kernel section %s version from %d to %d' % (
510 section, original_version, new_version))
511 self._kernel_handler.set_version(section, new_version)
512
513
514 @allow_multiple_section_input
515 def move_kernel_backward(self, section):
516 """Decrement kernel version for the requested section."""
517 self._modify_kernel_version(section, -1)
518
519
520 @allow_multiple_section_input
521 def move_kernel_forward(self, section):
522 """Increase kernel version for the requested section."""
523 self._modify_kernel_version(section, 1)
524
ctchangcc88d112012-08-23 17:56:15 +0800525
526 def retrieve_kernel_version(self, section):
527 """Return kernel version."""
528 return self._kernel_handler.get_version(section)
529
530
531 def retrieve_kernel_datakey_version(self, section):
532 """Return kernel datakey version."""
533 return self._kernel_handler.get_datakey_version(section)
534
535
Tom Wai-Hong Tam622d0ba2012-08-15 16:29:05 +0800536 def diff_kernel_a_b(self):
537 """Compare kernel A with B.
538
539 Returns:
540 True: if kernel A is different with B.
541 False: if kernel A is the same as B.
542 """
543 rootdev = self._chromeos_interface.get_root_dev()
544 kernel_a = self._chromeos_interface.join_part(rootdev, '3')
545 kernel_b = self._chromeos_interface.join_part(rootdev, '5')
546
547 # The signature (some kind of hash) for the kernel body is stored in
548 # the beginning. So compare the first 64KB (including header, preamble,
549 # and signature) should be enough to check them identical.
550 header_a = self._chromeos_interface.read_partition(kernel_a, 0x10000)
551 header_b = self._chromeos_interface.read_partition(kernel_b, 0x10000)
552
553 return header_a != header_b
Tom Wai-Hong Tam07278c22012-02-08 16:53:00 +0800554
Tom Wai-Hong Tam23870e02012-08-24 16:15:34 +0800555
Tom Wai-Hong Tam0a7b2be2012-10-15 16:44:12 +0800556 def is_removable_device_boot(self):
557 """Check the current boot device is removable.
558
559 Returns:
560 True: if a removable device boots.
561 False: if a non-removable device boots.
562 """
563 root_part = self._chromeos_interface.get_root_part()
564 return self._chromeos_interface.is_removable_device(root_part)
565
566
Tom Wai-Hong Tam23870e02012-08-24 16:15:34 +0800567 def setup_EC_image(self, ec_path):
568 """Setup the new EC image for later update.
569
570 Args:
571 ec_path: The path of the EC image to be updated.
572 """
573 self._ec_image = flashrom_handler.FlashromHandler()
574 self._ec_image.init(saft_flashrom_util,
575 self._chromeos_interface,
576 'ec_root_key.vpubk',
577 '/usr/share/vboot/devkeys',
578 'ec')
579 self._ec_image.new_image(ec_path)
580
581
582 def get_EC_image_sha(self):
583 """Get SHA1 hash of RW firmware section of the EC autest image."""
584 return self._ec_image.get_section_sha('rw')
585
586
587 def update_EC_from_image(self, section, flags):
588 """Update EC via software sync design.
589
590 It copys the RW section from the EC image, which is loaded by calling
591 setup_EC_image(), to the EC area of the specified RW section on the
592 current AP firmware.
593
594 Args:
595 section: A firmware section on current BIOS, either 'a' or 'b'.
596 flags: An integer of preamble flags.
597 """
598 blob = self._ec_image.get_section_body('rw')
599 self._bios_handler.set_section_ecbin(section, blob,
600 write_through=True)
601 self.set_firmware_flags(section, flags)
602
603
Tom Wai-Hong Tamb63bc742012-08-30 20:41:30 +0800604 def dump_firmware(self, bios_path):
605 """Dump the current BIOS firmware to a file, specified by bios_path.
606
607 Args:
608 bios_path: The path of the BIOS image to be written.
609 """
610 self._bios_handler.dump_whole(bios_path)
611
612
ctchang38ae4922012-09-03 17:01:16 +0800613 def dump_firmware_rw(self, dir_path):
614 """Dump the current BIOS firmware RW to dir_path.
615
616 VBOOTA, VBOOTB, FVMAIN, FVMAINB need to be dumped.
617
618 Args:
619 dir_path: The path of directory which contains files to be written.
620 """
621 if not os.path.isdir(dir_path):
622 raise Exception("%s doesn't exist" % dir_path)
623
624 VBOOTA_blob = self._bios_handler.get_section_sig('a')
625 VBOOTB_blob = self._bios_handler.get_section_sig('b')
626 FVMAIN_blob = self._bios_handler.get_section_body('a')
627 FVMAINB_blob = self._bios_handler.get_section_body('b')
628
629 open(os.path.join(dir_path, 'VBOOTA'), 'w').write(VBOOTA_blob)
630 open(os.path.join(dir_path, 'VBOOTB'), 'w').write(VBOOTB_blob)
631 open(os.path.join(dir_path, 'FVMAIN'), 'w').write(FVMAIN_blob)
632 open(os.path.join(dir_path, 'FVMAINB'), 'w').write(FVMAINB_blob)
633
634
Tom Wai-Hong Tamb63bc742012-08-30 20:41:30 +0800635 def write_firmware(self, bios_path):
636 """Write the firmware from bios_path to the current system.
637
638 Args:
639 bios_path: The path of the source BIOS image.
640 """
641 self._bios_handler.new_image(bios_path)
642 self._bios_handler.write_whole()
643
644
ctchang38ae4922012-09-03 17:01:16 +0800645 def write_firmware_rw(self, dir_path):
646 """Write the firmware RW from dir_path to the current system.
647
648 VBOOTA, VBOOTB, FVMAIN, FVMAINB need to be written.
649
650 Args:
651 dir_path: The path of directory which contains the source files.
652 """
653 if not os.path.exists(os.path.join(dir_path, 'VBOOTA')) or \
654 not os.path.exists(os.path.join(dir_path, 'VBOOTB')) or \
655 not os.path.exists(os.path.join(dir_path, 'FVMAIN')) or \
656 not os.path.exists(os.path.join(dir_path, 'FVMAINB')):
657 raise Exception("Source firmware file(s) doesn't exist.")
658
659 VBOOTA_blob = open(os.path.join(dir_path, 'VBOOTA'), 'rb').read()
660 VBOOTB_blob = open(os.path.join(dir_path, 'VBOOTB'), 'rb').read()
661 FVMAIN_blob = open(os.path.join(dir_path, 'FVMAIN'), 'rb').read()
662 FVMAINB_blob = open(os.path.join(dir_path, 'FVMAINB'), 'rb').read()
663
664 self._bios_handler.set_section_sig('a', VBOOTA_blob,
665 write_through=True)
666 self._bios_handler.set_section_sig('b', VBOOTB_blob,
667 write_through=True)
668 self._bios_handler.set_section_body('a', FVMAIN_blob,
669 write_through=True)
670 self._bios_handler.set_section_body('b', FVMAINB_blob,
671 write_through=True)
672
673
Tom Wai-Hong Tam23870e02012-08-24 16:15:34 +0800674 def dump_EC_firmware(self, ec_path):
675 """Dump the current EC firmware to a file, specified by ec_path.
676
677 Args:
678 ec_path: The path of the EC image to be written.
679 """
680 self._ec_handler.dump_whole(ec_path)
681
682
Tom Wai-Hong Tam44204b32012-11-20 13:55:40 +0800683 def set_EC_write_protect(self, enable):
684 """Enable write protect of the EC flash chip.
685
686 Args:
687 enable: True if activating EC write protect. Otherwise, False.
688 """
689 self._chromeos_interface.log('Requesting set EC write protect to %s' %
690 ('enable' if enable else 'disable'))
691 if enable:
692 self._ec_handler.enable_write_protect()
693 else:
694 self._ec_handler.disable_write_protect()
695
696
Tom Wai-Hong Tam48958832011-12-30 10:16:57 +0800697 def run_cgpt_test_loop(self):
698 """Run the CgptState test loop. The tst logic is handled in the client.
699
700 Returns:
701 0: there are more cgpt tests to execute.
702 1: no more CgptState test, finished.
703 """
704 return self._cgpt_state.test_loop()
705
706
707 def set_cgpt_test_step(self, step):
708 """Set the CgptState test step.
709
710 Args:
711 step: A test step number.
712 """
713 self._cgpt_state.set_step(step)
714
715
716 def get_cgpt_test_step(self):
717 """Get the CgptState test step.
718
719 Returns:
720 A test step number.
721 """
722 return self._cgpt_state.get_step()
723
724
ctchangcc88d112012-08-23 17:56:15 +0800725 def resign_kernel_with_keys(self, section, key_path=None):
726 """Resign kernel with temporary key."""
727 self._kernel_handler.resign_kernel(section, key_path)
728
729
ctchang38ae4922012-09-03 17:01:16 +0800730 def create_temp_dir(self, prefix='backup_'):
731 """Create a temporary directory and return the path."""
732 return tempfile.mkdtemp(prefix=prefix)
733
734
Chun-ting Changcf924e92012-10-29 13:49:01 +0800735 # for updater
736 def setup_updater(self, shellball=None):
737 """Setup the updater.
738
739 Args:
740 shellball: Path of provided shellball. Use default shellball
741 if None,
742 """
743 self._updater.setup(self._chromeos_interface, shellball)
744
745
746 def cleanup_updater(self):
747 self._updater.cleanup_temp_dir()
748
749
750 def retrieve_updater_fwid(self):
751 """Retrieve shellball's fwid.
752
753 This method should be called after updater_setup.
754
755 Returns:
756 Shellball's fwid.
757 """
758 return self._updater.retrieve_fwid()
759
760
761 def resign_updater_firmware(self, version):
762 """Resign firmware with version.
763
764 Args:
765 version: new version number.
766 """
767 self._updater.resign_firmware(version)
768
769
770 def repack_updater_shellball(self, append):
771 """Repack shellball with new fwid.
772
773 Args:
774 append: use for new fwid naming.
775 """
776 self._updater.repack_shellball(append)
777
778
779 def run_autoupdate(self, append):
780 """Run chromeos-firmwareupdate with autoupdate mode."""
781 options = ['--noupdate_ec', '--nocheck_rw_compatible']
782 self._updater.run_firmwareupdate(mode='autoupdate',
783 updater_append=append,
784 options=options)
785
786
787 def run_factory_install(self):
788 """Run chromeos-firmwareupdate with factory_install mode."""
789 options = ['--noupdate_ec']
790 self._updater.run_firmwareupdate(mode='factory_install',
791 options=options)
792
793
794 def run_bootok(self, append):
795 """Run chromeos-firmwareupdate with bootok mode."""
796 self._updater.run_firmwareupdate(mode='bootok',
797 updater_append=append)
798
799
800 def run_recovery(self):
801 """Run chromeos-firmwareupdate with recovery mode."""
802 options = ['--noupdate_ec', '--nocheck_rw_compatible']
803 self._updater.run_firmwareupdate(mode='recovery',
804 options=options)
805
806
807 def get_updater_temp_path(self):
808 """Get updater's temp directory path."""
809 return self._updater.get_temp_path()
810
811
812 def get_updater_keys_path(self):
813 """Get updater's keys directory path."""
814 return self._updater.get_keys_path()
815
816
817 def get_updater_work_path(self):
818 """Get updater's work directory path."""
819 return self._updater.get_work_path()
820
821
Tom Wai-Hong Tambea57b32011-09-02 18:27:47 +0800822 def cleanup(self):
823 """Cleanup for the RPC server. Currently nothing."""
824 pass
825
826
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700827def main():
828 parser = OptionParser(usage='Usage: %prog [options]')
829 parser.add_option('--port', type='int', dest='port', default=9990,
830 help='port number of XMLRPC server')
831 (options, args) = parser.parse_args()
832
833 faft_client = FAFTClient()
834
835 # Launch the XMLRPC server to provide FAFTClient commands.
Tom Wai-Hong Tam4a257e52011-11-12 08:36:22 +0800836 server = SimpleXMLRPCServer(('localhost', options.port), allow_none=True,
Tom Wai-Hong Tamc1e0b9a2012-11-01 13:52:39 +0800837 logRequests=True)
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700838 server.register_introspection_functions()
839 server.register_instance(faft_client)
840 print 'XMLRPC Server: Serving FAFTClient on port %s' % options.port
841 server.serve_forever()
842
843
844if __name__ == '__main__':
845 main()