blob: 5242f60f5cb07baaf83e328bd0bd90c7f51df305 [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
Chun-ting Changd43aa9b2012-11-16 10:12:05 +080060 be accessed remotely. Method naming should fit the naming rule
61 '_[categories]_[method_name]' where categories contains system, ec, bios,
62 kernel, cgpt, tpm, updater, etc. Methods should be called by
63 'FAFTClient.[categories].[method_name]', because _dispatch will rename
64 this name to '_[categories]_[method_name]'.
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -070065
66 Attributes:
67 _chromeos_interface: An object to encapsulate OS services functions.
Vic Yang59cac9c2012-05-21 15:28:42 +080068 _bios_handler: An object to automate BIOS flashrom testing.
69 _ec_handler: An object to automate EC flashrom testing.
Tom Wai-Hong Tam23870e02012-08-24 16:15:34 +080070 _ec_image: An object to automate EC image for autest.
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -070071 _kernel_handler: An object to provide kernel related actions.
72 _tpm_handler: An object to control TPM device.
Chun-ting Changcf924e92012-10-29 13:49:01 +080073 _updater: An object to update firmware.
ctchangc7e55ea2012-08-09 16:19:14 +080074 _temp_path: Path of a temp directory.
75 _keys_path: Path of a directory, keys/, in temp directory.
76 _work_path: Path of a directory, work/, in temp directory.
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -070077 """
78
79 def __init__(self):
80 """Initialize the data attributes of this class."""
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -070081 # TODO(waihong): Move the explicit object.init() methods to the
82 # objects' constructors (ChromeOSInterface, FlashromHandler,
83 # KernelHandler, and TpmHandler).
84 self._chromeos_interface = chromeos_interface.ChromeOSInterface(False)
Tom Wai-Hong Tam48958832011-12-30 10:16:57 +080085 # We keep the state of FAFT test in a permanent directory over reboots.
Tom Wai-Hong Tam07278c22012-02-08 16:53:00 +080086 state_dir = '/var/tmp/faft'
87 self._chromeos_interface.init(state_dir, log_file='/tmp/faft_log.txt')
88 os.chdir(state_dir)
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -070089
Vic Yang13d22ec2012-06-18 15:12:47 +080090 self._bios_handler = LazyFlashromHandlerProxy(
91 saft_flashrom_util,
Vic Yang59cac9c2012-05-21 15:28:42 +080092 self._chromeos_interface,
93 None,
94 '/usr/share/vboot/devkeys',
95 'bios')
Vic Yang59cac9c2012-05-21 15:28:42 +080096
Todd Brochf2b1d012012-06-14 12:55:21 -070097 self._ec_handler = None
98 if not os.system("mosys ec info"):
Vic Yang13d22ec2012-06-18 15:12:47 +080099 self._ec_handler = LazyFlashromHandlerProxy(
100 saft_flashrom_util,
Todd Brochf2b1d012012-06-14 12:55:21 -0700101 self._chromeos_interface,
Vic Yang13d22ec2012-06-18 15:12:47 +0800102 'ec_root_key.vpubk',
Todd Brochf2b1d012012-06-14 12:55:21 -0700103 '/usr/share/vboot/devkeys',
104 'ec')
Todd Brochf2b1d012012-06-14 12:55:21 -0700105
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700106
107 self._kernel_handler = kernel_handler.KernelHandler()
Tom Wai-Hong Tam07278c22012-02-08 16:53:00 +0800108 # TODO(waihong): The dev_key_path is a new argument. We do that in
109 # order not to break the old image and still be able to run.
110 try:
111 self._kernel_handler.init(self._chromeos_interface,
ctchangd60030f2012-08-29 15:39:56 +0800112 dev_key_path='/usr/share/vboot/devkeys',
113 internal_disk=True)
Tom Wai-Hong Tam07278c22012-02-08 16:53:00 +0800114 except:
115 # Copy the key to the current working directory.
116 shutil.copy('/usr/share/vboot/devkeys/kernel_data_key.vbprivk', '.')
ctchangd60030f2012-08-29 15:39:56 +0800117 self._kernel_handler.init(self._chromeos_interface,
118 internal_disk=True)
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700119
120 self._tpm_handler = tpm_handler.TpmHandler()
121 self._tpm_handler.init(self._chromeos_interface)
122
Tom Wai-Hong Tam48958832011-12-30 10:16:57 +0800123 self._cgpt_state = cgpt_state.CgptState(
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800124 'SHORT', self._chromeos_interface, self._system_get_root_dev())
Tom Wai-Hong Tam48958832011-12-30 10:16:57 +0800125
Chun-ting Changcf924e92012-10-29 13:49:01 +0800126 self._updater = FirmwareUpdater(self._chromeos_interface)
127
128
ctchangc7e55ea2012-08-09 16:19:14 +0800129 # Initialize temporary directory path
130 self._temp_path = '/var/tmp/faft/autest'
131 self._keys_path = os.path.join(self._temp_path, 'keys')
132 self._work_path = os.path.join(self._temp_path, 'work')
133
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700134
Tom Wai-Hong Tame8f291a2011-12-08 22:03:53 +0800135 def _dispatch(self, method, params):
136 """This _dispatch method handles string conversion especially.
137
138 Since we turn off allow_dotted_names option. So any string conversion,
139 like str(FAFTClient.method), i.e. FAFTClient.method.__str__, failed
140 via XML RPC call.
141 """
142 is_str = method.endswith('.__str__')
143 if is_str:
144 method = method.rsplit('.', 1)[0]
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800145
146 categories = ('system', 'bios', 'ec', 'kernel',
147 'tpm', 'cgpt', 'updater')
Tom Wai-Hong Tame8f291a2011-12-08 22:03:53 +0800148 try:
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800149 if method.split('.', 1)[0] in categories:
150 func = getattr(self, '_%s_%s' % (method.split('.',1)[0],
151 method.split('.',1)[1]))
152 else:
153 func = getattr(self, method)
Tom Wai-Hong Tame8f291a2011-12-08 22:03:53 +0800154 except AttributeError:
155 raise Exception('method "%s" is not supported' % method)
Tom Wai-Hong Tamc1a569f2012-12-04 15:07:25 +0800156
157 if is_str:
158 return str(func)
Tom Wai-Hong Tame8f291a2011-12-08 22:03:53 +0800159 else:
Tom Wai-Hong Tamc1a569f2012-12-04 15:07:25 +0800160 self._chromeos_interface.log('Dispatching method %s with args %s' %
161 (str(func), str(params)))
162 return func(*params)
Tom Wai-Hong Tame8f291a2011-12-08 22:03:53 +0800163
164
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800165 def _system_is_available(self):
Tom Wai-Hong Tambea57b32011-09-02 18:27:47 +0800166 """Function for polling the RPC server availability.
167
168 Returns:
169 Always True.
170 """
171 return True
172
173
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800174 def _system_run_shell_command(self, command):
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700175 """Run shell command.
176
177 Args:
178 command: A shell command to be run.
179 """
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700180 self._chromeos_interface.run_shell_command(command)
181
182
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800183 def _system_run_shell_command_get_output(self, command):
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700184 """Run shell command and get its console output.
185
186 Args:
187 command: A shell command to be run.
188
189 Returns:
190 A list of strings stripped of the newline characters.
191 """
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700192 return self._chromeos_interface.run_shell_command_get_output(command)
193
194
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800195 def _system_software_reboot(self):
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700196 """Request software reboot."""
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700197 self._chromeos_interface.run_shell_command('reboot')
198
199
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800200 def _system_get_platform_name(self):
Tom Wai-Hong Tam678ab152011-12-14 15:27:24 +0800201 """Get the platform name of the current system.
202
203 Returns:
204 A string of the platform name.
205 """
Vic Yang2bbb8672012-11-12 12:14:53 +0800206 # 'mosys platform name' sometimes fails. Let's get the verbose output.
207 lines = self._chromeos_interface.run_shell_command_get_output(
208 '(mosys -vvv platform name 2>&1) || echo Failed')
209 if lines[-1].strip() == 'Failed':
210 raise Exception('Failed getting platform name: ' + '\n'.join(lines))
211 return lines[-1]
Tom Wai-Hong Tam678ab152011-12-14 15:27:24 +0800212
213
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800214 def _system_get_crossystem_value(self, key):
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700215 """Get crossystem value of the requested key.
216
217 Args:
218 key: A crossystem key.
219
220 Returns:
221 A string of the requested crossystem value.
222 """
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700223 return self._chromeos_interface.run_shell_command_get_output(
224 'crossystem %s' % key)[0]
225
226
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800227 def _system_get_root_dev(self):
Tom Wai-Hong Tamcfda61f2011-11-02 17:41:01 +0800228 """Get the name of root device without partition number.
229
230 Returns:
231 A string of the root device without partition number.
232 """
Tom Wai-Hong Tamcfda61f2011-11-02 17:41:01 +0800233 return self._chromeos_interface.get_root_dev()
234
235
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800236 def _system_get_root_part(self):
Tom Wai-Hong Tamcfda61f2011-11-02 17:41:01 +0800237 """Get the name of root device with partition number.
238
239 Returns:
240 A string of the root device with partition number.
241 """
Tom Wai-Hong Tamcfda61f2011-11-02 17:41:01 +0800242 return self._chromeos_interface.get_root_part()
243
244
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800245 def _system_set_try_fw_b(self):
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700246 """Set 'Try Frimware B' flag in crossystem."""
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700247 self._chromeos_interface.cs.fwb_tries = 1
248
249
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800250 def _system_request_recovery_boot(self):
Tom Wai-Hong Tam76c75072011-10-25 18:00:12 +0800251 """Request running in recovery mode on the restart."""
Tom Wai-Hong Tam76c75072011-10-25 18:00:12 +0800252 self._chromeos_interface.cs.request_recovery()
253
254
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800255 def _system_get_dev_boot_usb(self):
Tom Wai-Hong Tam0a7b2be2012-10-15 16:44:12 +0800256 """Get dev_boot_usb value which controls developer mode boot from USB.
257
258 Returns:
259 True if enable, False if disable.
260 """
Tom Wai-Hong Tam0a7b2be2012-10-15 16:44:12 +0800261 return self._chromeos_interface.cs.dev_boot_usb == '1'
262
263
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800264 def _system_set_dev_boot_usb(self, value):
Tom Wai-Hong Tam0a7b2be2012-10-15 16:44:12 +0800265 """Set dev_boot_usb value which controls developer mode boot from USB.
266
267 Args:
268 value: True to enable, False to disable.
269 """
Tom Wai-Hong Tam0a7b2be2012-10-15 16:44:12 +0800270 self._chromeos_interface.cs.dev_boot_usb = 1 if value else 0
271
272
Tom Wai-Hong Tamc1a569f2012-12-04 15:07:25 +0800273 def _system_is_removable_device_boot(self):
274 """Check the current boot device is removable.
275
276 Returns:
277 True: if a removable device boots.
278 False: if a non-removable device boots.
279 """
280 root_part = self._chromeos_interface.get_root_part()
281 return self._chromeos_interface.is_removable_device(root_part)
282
283
284 def _system_create_temp_dir(self, prefix='backup_'):
285 """Create a temporary directory and return the path."""
286 return tempfile.mkdtemp(prefix=prefix)
287
288
289 def _bios_reload(self):
290 """Reload the firmware image that may be changed."""
291 self._bios_handler.reload()
292
293
294 def _bios_get_gbb_flags(self):
Tom Wai-Hong Tam8c9eed62011-12-28 15:05:05 +0800295 """Get the GBB flags.
296
297 Returns:
298 An integer of the GBB flags.
299 """
Vic Yang59cac9c2012-05-21 15:28:42 +0800300 return self._bios_handler.get_gbb_flags()
Tom Wai-Hong Tam8c9eed62011-12-28 15:05:05 +0800301
302
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800303 def _bios_get_preamble_flags(self, section):
Tom Wai-Hong Tam81f70002011-12-13 12:29:46 +0800304 """Get the preamble flags of a firmware section.
305
306 Args:
307 section: A firmware section, either 'a' or 'b'.
308
309 Returns:
310 An integer of the preamble flags.
311 """
Vic Yang59cac9c2012-05-21 15:28:42 +0800312 return self._bios_handler.get_section_flags(section)
313
314
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800315 def _bios_set_preamble_flags(self, section, flags):
Vic Yang91b73cf2012-07-31 17:18:11 +0800316 """Set the preamble flags of a firmware section.
317
318 Args:
319 section: A firmware section, either 'a' or 'b'.
320 flags: An integer of preamble flags.
321 """
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800322 version = self._bios_get_version(section)
Vic Yang91b73cf2012-07-31 17:18:11 +0800323 self._bios_handler.set_section_version(section, version, flags,
324 write_through=True)
325
326
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800327 def _bios_get_body_sha(self, section):
Tom Wai-Hong Tam4e10b9f2012-09-06 16:23:02 +0800328 """Get SHA1 hash of BIOS RW firmware section.
329
330 Args:
331 section: A firmware section, either 'a' or 'b'.
332 flags: An integer of preamble flags.
333 """
334 return self._bios_handler.get_section_sha(section)
335
336
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800337 def _bios_get_sig_sha(self, section):
ctchang38ae4922012-09-03 17:01:16 +0800338 """Get SHA1 hash of firmware vblock in section."""
339 return self._bios_handler.get_section_sig_sha(section)
340
341
Tom Wai-Hong Tam0e680af2011-10-26 14:32:55 +0800342 @allow_multiple_section_input
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800343 def _bios_corrupt_sig(self, section):
Tom Wai-Hong Tam9aea8212011-12-12 15:08:45 +0800344 """Corrupt the requested firmware section signature.
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700345
346 Args:
347 section: A firmware section, either 'a' or 'b'.
348 """
Vic Yang59cac9c2012-05-21 15:28:42 +0800349 self._bios_handler.corrupt_firmware(section)
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700350
351
Tom Wai-Hong Tam0e680af2011-10-26 14:32:55 +0800352 @allow_multiple_section_input
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800353 def _bios_restore_sig(self, section):
Tom Wai-Hong Tam9aea8212011-12-12 15:08:45 +0800354 """Restore the previously corrupted firmware section signature.
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700355
356 Args:
357 section: A firmware section, either 'a' or 'b'.
358 """
Vic Yang59cac9c2012-05-21 15:28:42 +0800359 self._bios_handler.restore_firmware(section)
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700360
361
Tom Wai-Hong Tamcfda61f2011-11-02 17:41:01 +0800362 @allow_multiple_section_input
Tom Wai-Hong Tamc1a569f2012-12-04 15:07:25 +0800363 def _bios_corrupt_body(self, section):
364 """Corrupt the requested firmware section body.
365
366 Args:
367 section: A firmware section, either 'a' or 'b'.
368 """
369 self._bios_handler.corrupt_firmware_body(section)
370
371
372 @allow_multiple_section_input
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800373 def _bios_restore_body(self, section):
Tom Wai-Hong Tam81f70002011-12-13 12:29:46 +0800374 """Restore the previously corrupted firmware section body.
375
376 Args:
377 section: A firmware section, either 'a' or 'b'.
378 """
Vic Yang59cac9c2012-05-21 15:28:42 +0800379 self._bios_handler.restore_firmware_body(section)
Tom Wai-Hong Tam81f70002011-12-13 12:29:46 +0800380
381
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800382 def __bios_modify_version(self, section, delta):
Tom Wai-Hong Tam46d03b12012-02-08 12:02:17 +0800383 """Modify firmware version for the requested section, by adding delta.
384
385 The passed in delta, a positive or a negative number, is added to the
386 original firmware version.
387 """
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800388 original_version = self._bios_get_version(section)
Tom Wai-Hong Tam46d03b12012-02-08 12:02:17 +0800389 new_version = original_version + delta
Vic Yang59cac9c2012-05-21 15:28:42 +0800390 flags = self._bios_handler.get_section_flags(section)
Tom Wai-Hong Tam46d03b12012-02-08 12:02:17 +0800391 self._chromeos_interface.log(
392 'Setting firmware section %s version from %d to %d' % (
393 section, original_version, new_version))
Vic Yang59cac9c2012-05-21 15:28:42 +0800394 self._bios_handler.set_section_version(section, new_version, flags,
395 write_through=True)
Tom Wai-Hong Tam46d03b12012-02-08 12:02:17 +0800396
Tom Wai-Hong Tamc1a569f2012-12-04 15:07:25 +0800397
Tom Wai-Hong Tam46d03b12012-02-08 12:02:17 +0800398 @allow_multiple_section_input
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800399 def _bios_move_version_backward(self, section):
Tom Wai-Hong Tam46d03b12012-02-08 12:02:17 +0800400 """Decrement firmware version for the requested section."""
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800401 self.__bios_modify_version(section, -1)
Tom Wai-Hong Tam46d03b12012-02-08 12:02:17 +0800402
403
404 @allow_multiple_section_input
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800405 def _bios_move_version_forward(self, section):
Tom Wai-Hong Tam46d03b12012-02-08 12:02:17 +0800406 """Increase firmware version for the requested section."""
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800407 self.__bios_modify_version(section, 1)
Tom Wai-Hong Tam46d03b12012-02-08 12:02:17 +0800408
Tom Wai-Hong Tamc1a569f2012-12-04 15:07:25 +0800409
410 def _bios_get_version(self, section):
411 """Retrieve firmware version of a section."""
412 return self._bios_handler.get_section_version(section)
413
414
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800415 def _bios_get_datakey_version(self, section):
ctchangc7e55ea2012-08-09 16:19:14 +0800416 """Return firmware data key version."""
417 return self._bios_handler.get_section_datakey_version(section)
418
Chun-ting Changa4f65532012-10-17 16:57:28 +0800419
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800420 def _bios_get_kernel_subkey_version(self,section):
ctchangc7e55ea2012-08-09 16:19:14 +0800421 """Return kernel subkey version."""
422 return self._bios_handler.get_section_kernel_subkey_version(section)
Tom Wai-Hong Tam46d03b12012-02-08 12:02:17 +0800423
Tom Wai-Hong Tam0a7b2be2012-10-15 16:44:12 +0800424
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800425 def _bios_setup_EC_image(self, ec_path):
Tom Wai-Hong Tam23870e02012-08-24 16:15:34 +0800426 """Setup the new EC image for later update.
427
428 Args:
429 ec_path: The path of the EC image to be updated.
430 """
431 self._ec_image = flashrom_handler.FlashromHandler()
432 self._ec_image.init(saft_flashrom_util,
433 self._chromeos_interface,
434 'ec_root_key.vpubk',
435 '/usr/share/vboot/devkeys',
436 'ec')
437 self._ec_image.new_image(ec_path)
438
439
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800440 def _bios_get_EC_image_sha(self):
Tom Wai-Hong Tam23870e02012-08-24 16:15:34 +0800441 """Get SHA1 hash of RW firmware section of the EC autest image."""
442 return self._ec_image.get_section_sha('rw')
443
444
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800445 def _bios_update_EC_from_image(self, section, flags):
Tom Wai-Hong Tam23870e02012-08-24 16:15:34 +0800446 """Update EC via software sync design.
447
448 It copys the RW section from the EC image, which is loaded by calling
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800449 bios_setup_EC_image(), to the EC area of the specified RW section on the
Tom Wai-Hong Tam23870e02012-08-24 16:15:34 +0800450 current AP firmware.
451
452 Args:
453 section: A firmware section on current BIOS, either 'a' or 'b'.
454 flags: An integer of preamble flags.
455 """
456 blob = self._ec_image.get_section_body('rw')
457 self._bios_handler.set_section_ecbin(section, blob,
458 write_through=True)
459 self.set_firmware_flags(section, flags)
460
461
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800462 def _bios_dump_whole(self, bios_path):
Tom Wai-Hong Tamb63bc742012-08-30 20:41:30 +0800463 """Dump the current BIOS firmware to a file, specified by bios_path.
464
465 Args:
466 bios_path: The path of the BIOS image to be written.
467 """
468 self._bios_handler.dump_whole(bios_path)
469
470
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800471 def _bios_dump_rw(self, dir_path):
ctchang38ae4922012-09-03 17:01:16 +0800472 """Dump the current BIOS firmware RW to dir_path.
473
474 VBOOTA, VBOOTB, FVMAIN, FVMAINB need to be dumped.
475
476 Args:
477 dir_path: The path of directory which contains files to be written.
478 """
479 if not os.path.isdir(dir_path):
480 raise Exception("%s doesn't exist" % dir_path)
481
482 VBOOTA_blob = self._bios_handler.get_section_sig('a')
483 VBOOTB_blob = self._bios_handler.get_section_sig('b')
484 FVMAIN_blob = self._bios_handler.get_section_body('a')
485 FVMAINB_blob = self._bios_handler.get_section_body('b')
486
487 open(os.path.join(dir_path, 'VBOOTA'), 'w').write(VBOOTA_blob)
488 open(os.path.join(dir_path, 'VBOOTB'), 'w').write(VBOOTB_blob)
489 open(os.path.join(dir_path, 'FVMAIN'), 'w').write(FVMAIN_blob)
490 open(os.path.join(dir_path, 'FVMAINB'), 'w').write(FVMAINB_blob)
491
492
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800493 def _bios_write_whole(self, bios_path):
Tom Wai-Hong Tamb63bc742012-08-30 20:41:30 +0800494 """Write the firmware from bios_path to the current system.
495
496 Args:
497 bios_path: The path of the source BIOS image.
498 """
499 self._bios_handler.new_image(bios_path)
500 self._bios_handler.write_whole()
501
502
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800503 def _bios_write_rw(self, dir_path):
ctchang38ae4922012-09-03 17:01:16 +0800504 """Write the firmware RW from dir_path to the current system.
505
506 VBOOTA, VBOOTB, FVMAIN, FVMAINB need to be written.
507
508 Args:
509 dir_path: The path of directory which contains the source files.
510 """
511 if not os.path.exists(os.path.join(dir_path, 'VBOOTA')) or \
512 not os.path.exists(os.path.join(dir_path, 'VBOOTB')) or \
513 not os.path.exists(os.path.join(dir_path, 'FVMAIN')) or \
514 not os.path.exists(os.path.join(dir_path, 'FVMAINB')):
515 raise Exception("Source firmware file(s) doesn't exist.")
516
517 VBOOTA_blob = open(os.path.join(dir_path, 'VBOOTA'), 'rb').read()
518 VBOOTB_blob = open(os.path.join(dir_path, 'VBOOTB'), 'rb').read()
519 FVMAIN_blob = open(os.path.join(dir_path, 'FVMAIN'), 'rb').read()
520 FVMAINB_blob = open(os.path.join(dir_path, 'FVMAINB'), 'rb').read()
521
522 self._bios_handler.set_section_sig('a', VBOOTA_blob,
523 write_through=True)
524 self._bios_handler.set_section_sig('b', VBOOTB_blob,
525 write_through=True)
526 self._bios_handler.set_section_body('a', FVMAIN_blob,
527 write_through=True)
528 self._bios_handler.set_section_body('b', FVMAINB_blob,
529 write_through=True)
530
531
Tom Wai-Hong Tamc1a569f2012-12-04 15:07:25 +0800532 def _ec_get_version(self):
533 """Get EC version via mosys.
534
535 Returns:
536 A string of the EC version.
537 """
538 return self._chromeos_interface.run_shell_command_get_output(
539 'mosys ec info | sed "s/.*| //"')[0]
540
541
542 def _ec_get_firmware_sha(self):
543 """Get SHA1 hash of EC RW firmware section."""
544 return self._ec_handler.get_section_sha('rw')
545
546
547 @allow_multiple_section_input
548 def _ec_corrupt_sig(self, section):
549 """Corrupt the requested EC section signature.
550
551 Args:
552 section: A EC section, either 'a' or 'b'.
553 """
554 self._ec_handler.corrupt_firmware(section, corrupt_all=True)
555
556
557 @allow_multiple_section_input
558 def _ec_restore_sig(self, section):
559 """Restore the previously corrupted EC section signature.
560
561 Args:
562 section: An EC section, either 'a' or 'b'.
563 """
564 self._ec_handler.restore_firmware(section, restore_all=True)
565
566
567 @allow_multiple_section_input
568 def _ec_corrupt_body(self, section):
569 """Corrupt the requested EC section body.
570
571 Args:
572 section: An EC section, either 'a' or 'b'.
573 """
574 self._ec_handler.corrupt_firmware_body(section, corrupt_all=True)
575
576
577 @allow_multiple_section_input
578 def _ec_restore_body(self, section):
579 """Restore the previously corrupted EC section body.
580
581 Args:
582 section: An EC section, either 'a' or 'b'.
583 """
584 self._ec_handler.restore_firmware_body(section, restore_all=True)
585
586
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800587 def _ec_dump_firmware(self, ec_path):
Tom Wai-Hong Tam23870e02012-08-24 16:15:34 +0800588 """Dump the current EC firmware to a file, specified by ec_path.
589
590 Args:
591 ec_path: The path of the EC image to be written.
592 """
593 self._ec_handler.dump_whole(ec_path)
594
595
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800596 def _ec_set_write_protect(self, enable):
Tom Wai-Hong Tam44204b32012-11-20 13:55:40 +0800597 """Enable write protect of the EC flash chip.
598
599 Args:
600 enable: True if activating EC write protect. Otherwise, False.
601 """
Tom Wai-Hong Tam44204b32012-11-20 13:55:40 +0800602 if enable:
603 self._ec_handler.enable_write_protect()
604 else:
605 self._ec_handler.disable_write_protect()
606
607
Tom Wai-Hong Tamc1a569f2012-12-04 15:07:25 +0800608 @allow_multiple_section_input
609 def _kernel_corrupt_sig(self, section):
610 """Corrupt the requested kernel section.
611
612 Args:
613 section: A kernel section, either 'a' or 'b'.
614 """
615 self._kernel_handler.corrupt_kernel(section)
616
617
618 @allow_multiple_section_input
619 def _kernel_restore_sig(self, section):
620 """Restore the requested kernel section (previously corrupted).
621
622 Args:
623 section: A kernel section, either 'a' or 'b'.
624 """
625 self._kernel_handler.restore_kernel(section)
626
627
628 def __kernel_modify_version(self, section, delta):
629 """Modify kernel version for the requested section, by adding delta.
630
631 The passed in delta, a positive or a negative number, is added to the
632 original kernel version.
633 """
634 original_version = self._kernel_handler.get_version(section)
635 new_version = original_version + delta
636 self._chromeos_interface.log(
637 'Setting kernel section %s version from %d to %d' % (
638 section, original_version, new_version))
639 self._kernel_handler.set_version(section, new_version)
640
641
642 @allow_multiple_section_input
643 def _kernel_move_version_backward(self, section):
644 """Decrement kernel version for the requested section."""
645 self.__kernel_modify_version(section, -1)
646
647
648 @allow_multiple_section_input
649 def _kernel_move_version_forward(self, section):
650 """Increase kernel version for the requested section."""
651 self.__kernel_modify_version(section, 1)
652
653
654 def _kernel_get_version(self, section):
655 """Return kernel version."""
656 return self._kernel_handler.get_version(section)
657
658
659 def _kernel_get_datakey_version(self, section):
660 """Return kernel datakey version."""
661 return self._kernel_handler.get_datakey_version(section)
662
663
664 def _kernel_diff_a_b(self):
665 """Compare kernel A with B.
666
667 Returns:
668 True: if kernel A is different with B.
669 False: if kernel A is the same as B.
670 """
671 rootdev = self._chromeos_interface.get_root_dev()
672 kernel_a = self._chromeos_interface.join_part(rootdev, '3')
673 kernel_b = self._chromeos_interface.join_part(rootdev, '5')
674
675 # The signature (some kind of hash) for the kernel body is stored in
676 # the beginning. So compare the first 64KB (including header, preamble,
677 # and signature) should be enough to check them identical.
678 header_a = self._chromeos_interface.read_partition(kernel_a, 0x10000)
679 header_b = self._chromeos_interface.read_partition(kernel_b, 0x10000)
680
681 return header_a != header_b
682
683
684 def _kernel_resign_with_keys(self, section, key_path=None):
685 """Resign kernel with temporary key."""
686 self._kernel_handler.resign_kernel(section, key_path)
687
688
689 def _tpm_get_firmware_version(self):
690 """Retrieve tpm firmware body version."""
691 return self._tpm_handler.get_fw_version()
692
693
694 def _tpm_get_firmware_datakey_version(self):
695 """Retrieve tpm firmware data key version."""
696 return self._tpm_handler.get_fw_body_version()
697
698
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800699 def _cgpt_run_test_loop(self):
Tom Wai-Hong Tam48958832011-12-30 10:16:57 +0800700 """Run the CgptState test loop. The tst logic is handled in the client.
701
702 Returns:
703 0: there are more cgpt tests to execute.
704 1: no more CgptState test, finished.
705 """
706 return self._cgpt_state.test_loop()
707
708
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800709 def _cgpt_set_test_step(self, step):
Tom Wai-Hong Tam48958832011-12-30 10:16:57 +0800710 """Set the CgptState test step.
711
712 Args:
713 step: A test step number.
714 """
715 self._cgpt_state.set_step(step)
716
717
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800718 def _cgpt_get_test_step(self):
Tom Wai-Hong Tam48958832011-12-30 10:16:57 +0800719 """Get the CgptState test step.
720
721 Returns:
722 A test step number.
723 """
724 return self._cgpt_state.get_step()
725
726
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800727 def _updater_setup(self, shellball=None):
Chun-ting Changcf924e92012-10-29 13:49:01 +0800728 """Setup the updater.
729
730 Args:
731 shellball: Path of provided shellball. Use default shellball
732 if None,
733 """
734 self._updater.setup(self._chromeos_interface, shellball)
735
736
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800737 def _updater_cleanup(self):
Chun-ting Changcf924e92012-10-29 13:49:01 +0800738 self._updater.cleanup_temp_dir()
739
740
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800741 def _updater_get_fwid(self):
Chun-ting Changcf924e92012-10-29 13:49:01 +0800742 """Retrieve shellball's fwid.
743
744 This method should be called after updater_setup.
745
746 Returns:
747 Shellball's fwid.
748 """
749 return self._updater.retrieve_fwid()
750
751
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800752 def _updater_resign_firmware(self, version):
Chun-ting Changcf924e92012-10-29 13:49:01 +0800753 """Resign firmware with version.
754
755 Args:
756 version: new version number.
757 """
758 self._updater.resign_firmware(version)
759
760
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800761 def _updater_repack_shellball(self, append):
Chun-ting Changcf924e92012-10-29 13:49:01 +0800762 """Repack shellball with new fwid.
763
764 Args:
765 append: use for new fwid naming.
766 """
767 self._updater.repack_shellball(append)
768
769
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800770 def _updater_run_autoupdate(self, append):
Chun-ting Changcf924e92012-10-29 13:49:01 +0800771 """Run chromeos-firmwareupdate with autoupdate mode."""
772 options = ['--noupdate_ec', '--nocheck_rw_compatible']
773 self._updater.run_firmwareupdate(mode='autoupdate',
774 updater_append=append,
775 options=options)
776
777
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800778 def _updater_run_factory_install(self):
Chun-ting Changcf924e92012-10-29 13:49:01 +0800779 """Run chromeos-firmwareupdate with factory_install mode."""
780 options = ['--noupdate_ec']
781 self._updater.run_firmwareupdate(mode='factory_install',
782 options=options)
783
784
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800785 def _updater_run_bootok(self, append):
Chun-ting Changcf924e92012-10-29 13:49:01 +0800786 """Run chromeos-firmwareupdate with bootok mode."""
787 self._updater.run_firmwareupdate(mode='bootok',
788 updater_append=append)
789
790
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800791 def _updater_run_recovery(self):
Chun-ting Changcf924e92012-10-29 13:49:01 +0800792 """Run chromeos-firmwareupdate with recovery mode."""
793 options = ['--noupdate_ec', '--nocheck_rw_compatible']
794 self._updater.run_firmwareupdate(mode='recovery',
795 options=options)
796
797
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800798 def _updater_get_temp_path(self):
Chun-ting Changcf924e92012-10-29 13:49:01 +0800799 """Get updater's temp directory path."""
800 return self._updater.get_temp_path()
801
802
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800803 def _updater_get_keys_path(self):
Chun-ting Changcf924e92012-10-29 13:49:01 +0800804 """Get updater's keys directory path."""
805 return self._updater.get_keys_path()
806
807
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800808 def _updater_get_work_path(self):
Chun-ting Changcf924e92012-10-29 13:49:01 +0800809 """Get updater's work directory path."""
810 return self._updater.get_work_path()
811
812
Tom Wai-Hong Tambea57b32011-09-02 18:27:47 +0800813 def cleanup(self):
814 """Cleanup for the RPC server. Currently nothing."""
815 pass
816
817
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700818def main():
819 parser = OptionParser(usage='Usage: %prog [options]')
820 parser.add_option('--port', type='int', dest='port', default=9990,
821 help='port number of XMLRPC server')
822 (options, args) = parser.parse_args()
823
824 faft_client = FAFTClient()
825
826 # Launch the XMLRPC server to provide FAFTClient commands.
Tom Wai-Hong Tam4a257e52011-11-12 08:36:22 +0800827 server = SimpleXMLRPCServer(('localhost', options.port), allow_none=True,
Tom Wai-Hong Tamc1e0b9a2012-11-01 13:52:39 +0800828 logRequests=True)
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700829 server.register_introspection_functions()
830 server.register_instance(faft_client)
831 print 'XMLRPC Server: Serving FAFTClient on port %s' % options.port
832 server.serve_forever()
833
834
835if __name__ == '__main__':
836 main()