blob: 3b9be90160d0fdaddafeec0a5fca56c814721ea7 [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.
Tom Wai-Hong Tam48ae2212013-06-26 10:37:40 +080072 _log_file: Path of the log file.
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -070073 _tpm_handler: An object to control TPM device.
Chun-ting Changcf924e92012-10-29 13:49:01 +080074 _updater: An object to update firmware.
ctchangc7e55ea2012-08-09 16:19:14 +080075 _temp_path: Path of a temp directory.
76 _keys_path: Path of a directory, keys/, in temp directory.
77 _work_path: Path of a directory, work/, in temp directory.
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -070078 """
79
80 def __init__(self):
81 """Initialize the data attributes of this class."""
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -070082 # TODO(waihong): Move the explicit object.init() methods to the
83 # objects' constructors (ChromeOSInterface, FlashromHandler,
84 # KernelHandler, and TpmHandler).
85 self._chromeos_interface = chromeos_interface.ChromeOSInterface(False)
Tom Wai-Hong Tam48958832011-12-30 10:16:57 +080086 # We keep the state of FAFT test in a permanent directory over reboots.
Tom Wai-Hong Tam07278c22012-02-08 16:53:00 +080087 state_dir = '/var/tmp/faft'
Tom Wai-Hong Tam07278c22012-02-08 16:53:00 +080088 os.chdir(state_dir)
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -070089
Tom Wai-Hong Tam48ae2212013-06-26 10:37:40 +080090 self._log_file = os.path.join(state_dir, 'faft_client.log')
91 self._chromeos_interface.init(state_dir, log_file=self._log_file)
92
Vic Yang13d22ec2012-06-18 15:12:47 +080093 self._bios_handler = LazyFlashromHandlerProxy(
94 saft_flashrom_util,
Vic Yang59cac9c2012-05-21 15:28:42 +080095 self._chromeos_interface,
96 None,
97 '/usr/share/vboot/devkeys',
98 'bios')
Vic Yang59cac9c2012-05-21 15:28:42 +080099
Todd Brochf2b1d012012-06-14 12:55:21 -0700100 self._ec_handler = None
101 if not os.system("mosys ec info"):
Vic Yang13d22ec2012-06-18 15:12:47 +0800102 self._ec_handler = LazyFlashromHandlerProxy(
103 saft_flashrom_util,
Todd Brochf2b1d012012-06-14 12:55:21 -0700104 self._chromeos_interface,
Vic Yang13d22ec2012-06-18 15:12:47 +0800105 'ec_root_key.vpubk',
Todd Brochf2b1d012012-06-14 12:55:21 -0700106 '/usr/share/vboot/devkeys',
107 'ec')
Todd Brochf2b1d012012-06-14 12:55:21 -0700108
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700109
110 self._kernel_handler = kernel_handler.KernelHandler()
Tom Wai-Hong Tam07278c22012-02-08 16:53:00 +0800111 # TODO(waihong): The dev_key_path is a new argument. We do that in
112 # order not to break the old image and still be able to run.
113 try:
114 self._kernel_handler.init(self._chromeos_interface,
ctchangd60030f2012-08-29 15:39:56 +0800115 dev_key_path='/usr/share/vboot/devkeys',
116 internal_disk=True)
Tom Wai-Hong Tam07278c22012-02-08 16:53:00 +0800117 except:
118 # Copy the key to the current working directory.
119 shutil.copy('/usr/share/vboot/devkeys/kernel_data_key.vbprivk', '.')
ctchangd60030f2012-08-29 15:39:56 +0800120 self._kernel_handler.init(self._chromeos_interface,
121 internal_disk=True)
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700122
123 self._tpm_handler = tpm_handler.TpmHandler()
124 self._tpm_handler.init(self._chromeos_interface)
125
Tom Wai-Hong Tam48958832011-12-30 10:16:57 +0800126 self._cgpt_state = cgpt_state.CgptState(
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800127 'SHORT', self._chromeos_interface, self._system_get_root_dev())
Tom Wai-Hong Tam48958832011-12-30 10:16:57 +0800128
Chun-ting Changcf924e92012-10-29 13:49:01 +0800129 self._updater = FirmwareUpdater(self._chromeos_interface)
130
131
ctchangc7e55ea2012-08-09 16:19:14 +0800132 # Initialize temporary directory path
133 self._temp_path = '/var/tmp/faft/autest'
134 self._keys_path = os.path.join(self._temp_path, 'keys')
135 self._work_path = os.path.join(self._temp_path, 'work')
136
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700137
Tom Wai-Hong Tame8f291a2011-12-08 22:03:53 +0800138 def _dispatch(self, method, params):
139 """This _dispatch method handles string conversion especially.
140
141 Since we turn off allow_dotted_names option. So any string conversion,
142 like str(FAFTClient.method), i.e. FAFTClient.method.__str__, failed
143 via XML RPC call.
144 """
145 is_str = method.endswith('.__str__')
146 if is_str:
147 method = method.rsplit('.', 1)[0]
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800148
149 categories = ('system', 'bios', 'ec', 'kernel',
150 'tpm', 'cgpt', 'updater')
Tom Wai-Hong Tame8f291a2011-12-08 22:03:53 +0800151 try:
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800152 if method.split('.', 1)[0] in categories:
153 func = getattr(self, '_%s_%s' % (method.split('.',1)[0],
154 method.split('.',1)[1]))
155 else:
156 func = getattr(self, method)
Tom Wai-Hong Tame8f291a2011-12-08 22:03:53 +0800157 except AttributeError:
158 raise Exception('method "%s" is not supported' % method)
Tom Wai-Hong Tamc1a569f2012-12-04 15:07:25 +0800159
160 if is_str:
161 return str(func)
Tom Wai-Hong Tame8f291a2011-12-08 22:03:53 +0800162 else:
Tom Wai-Hong Tamc1a569f2012-12-04 15:07:25 +0800163 self._chromeos_interface.log('Dispatching method %s with args %s' %
164 (str(func), str(params)))
165 return func(*params)
Tom Wai-Hong Tame8f291a2011-12-08 22:03:53 +0800166
167
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800168 def _system_is_available(self):
Tom Wai-Hong Tambea57b32011-09-02 18:27:47 +0800169 """Function for polling the RPC server availability.
170
171 Returns:
172 Always True.
173 """
174 return True
175
176
Tom Wai-Hong Tam48ae2212013-06-26 10:37:40 +0800177 def _system_dump_log(self, remove_log=False):
178 """Dump the log file.
179
180 Args:
181 remove_log: Remove the log file after dump.
182
183 Returns:
184 String of the log file content.
185 """
186 log = open(self._log_file).read()
187 if remove_log:
188 os.remove(self._log_file)
189 return log
190
191
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800192 def _system_run_shell_command(self, command):
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700193 """Run shell command.
194
195 Args:
196 command: A shell command to be run.
197 """
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700198 self._chromeos_interface.run_shell_command(command)
199
200
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800201 def _system_run_shell_command_get_output(self, command):
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700202 """Run shell command and get its console output.
203
204 Args:
205 command: A shell command to be run.
206
207 Returns:
208 A list of strings stripped of the newline characters.
209 """
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700210 return self._chromeos_interface.run_shell_command_get_output(command)
211
212
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800213 def _system_software_reboot(self):
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700214 """Request software reboot."""
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700215 self._chromeos_interface.run_shell_command('reboot')
216
217
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800218 def _system_get_platform_name(self):
Tom Wai-Hong Tam678ab152011-12-14 15:27:24 +0800219 """Get the platform name of the current system.
220
221 Returns:
222 A string of the platform name.
223 """
Vic Yang2bbb8672012-11-12 12:14:53 +0800224 # 'mosys platform name' sometimes fails. Let's get the verbose output.
225 lines = self._chromeos_interface.run_shell_command_get_output(
226 '(mosys -vvv platform name 2>&1) || echo Failed')
227 if lines[-1].strip() == 'Failed':
228 raise Exception('Failed getting platform name: ' + '\n'.join(lines))
229 return lines[-1]
Tom Wai-Hong Tam678ab152011-12-14 15:27:24 +0800230
231
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800232 def _system_get_crossystem_value(self, key):
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700233 """Get crossystem value of the requested key.
234
235 Args:
236 key: A crossystem key.
237
238 Returns:
239 A string of the requested crossystem value.
240 """
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700241 return self._chromeos_interface.run_shell_command_get_output(
242 'crossystem %s' % key)[0]
243
244
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800245 def _system_get_root_dev(self):
Tom Wai-Hong Tamcfda61f2011-11-02 17:41:01 +0800246 """Get the name of root device without partition number.
247
248 Returns:
249 A string of the root device without partition number.
250 """
Tom Wai-Hong Tamcfda61f2011-11-02 17:41:01 +0800251 return self._chromeos_interface.get_root_dev()
252
253
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800254 def _system_get_root_part(self):
Tom Wai-Hong Tamcfda61f2011-11-02 17:41:01 +0800255 """Get the name of root device with partition number.
256
257 Returns:
258 A string of the root device with partition number.
259 """
Tom Wai-Hong Tamcfda61f2011-11-02 17:41:01 +0800260 return self._chromeos_interface.get_root_part()
261
262
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800263 def _system_set_try_fw_b(self):
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700264 """Set 'Try Frimware B' flag in crossystem."""
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700265 self._chromeos_interface.cs.fwb_tries = 1
266
267
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800268 def _system_request_recovery_boot(self):
Tom Wai-Hong Tam76c75072011-10-25 18:00:12 +0800269 """Request running in recovery mode on the restart."""
Tom Wai-Hong Tam76c75072011-10-25 18:00:12 +0800270 self._chromeos_interface.cs.request_recovery()
271
272
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800273 def _system_get_dev_boot_usb(self):
Tom Wai-Hong Tam0a7b2be2012-10-15 16:44:12 +0800274 """Get dev_boot_usb value which controls developer mode boot from USB.
275
276 Returns:
277 True if enable, False if disable.
278 """
Tom Wai-Hong Tam0a7b2be2012-10-15 16:44:12 +0800279 return self._chromeos_interface.cs.dev_boot_usb == '1'
280
281
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800282 def _system_set_dev_boot_usb(self, value):
Tom Wai-Hong Tam0a7b2be2012-10-15 16:44:12 +0800283 """Set dev_boot_usb value which controls developer mode boot from USB.
284
285 Args:
286 value: True to enable, False to disable.
287 """
Tom Wai-Hong Tam0a7b2be2012-10-15 16:44:12 +0800288 self._chromeos_interface.cs.dev_boot_usb = 1 if value else 0
289
290
Tom Wai-Hong Tamc1a569f2012-12-04 15:07:25 +0800291 def _system_is_removable_device_boot(self):
292 """Check the current boot device is removable.
293
294 Returns:
295 True: if a removable device boots.
296 False: if a non-removable device boots.
297 """
298 root_part = self._chromeos_interface.get_root_part()
299 return self._chromeos_interface.is_removable_device(root_part)
300
301
302 def _system_create_temp_dir(self, prefix='backup_'):
303 """Create a temporary directory and return the path."""
304 return tempfile.mkdtemp(prefix=prefix)
305
306
307 def _bios_reload(self):
308 """Reload the firmware image that may be changed."""
309 self._bios_handler.reload()
310
311
312 def _bios_get_gbb_flags(self):
Tom Wai-Hong Tam8c9eed62011-12-28 15:05:05 +0800313 """Get the GBB flags.
314
315 Returns:
316 An integer of the GBB flags.
317 """
Vic Yang59cac9c2012-05-21 15:28:42 +0800318 return self._bios_handler.get_gbb_flags()
Tom Wai-Hong Tam8c9eed62011-12-28 15:05:05 +0800319
320
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800321 def _bios_get_preamble_flags(self, section):
Tom Wai-Hong Tam81f70002011-12-13 12:29:46 +0800322 """Get the preamble flags of a firmware section.
323
324 Args:
325 section: A firmware section, either 'a' or 'b'.
326
327 Returns:
328 An integer of the preamble flags.
329 """
Vic Yang59cac9c2012-05-21 15:28:42 +0800330 return self._bios_handler.get_section_flags(section)
331
332
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800333 def _bios_set_preamble_flags(self, section, flags):
Vic Yang91b73cf2012-07-31 17:18:11 +0800334 """Set the preamble flags of a firmware section.
335
336 Args:
337 section: A firmware section, either 'a' or 'b'.
338 flags: An integer of preamble flags.
339 """
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800340 version = self._bios_get_version(section)
Vic Yang91b73cf2012-07-31 17:18:11 +0800341 self._bios_handler.set_section_version(section, version, flags,
342 write_through=True)
343
344
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800345 def _bios_get_body_sha(self, section):
Tom Wai-Hong Tam4e10b9f2012-09-06 16:23:02 +0800346 """Get SHA1 hash of BIOS RW firmware section.
347
348 Args:
349 section: A firmware section, either 'a' or 'b'.
350 flags: An integer of preamble flags.
351 """
352 return self._bios_handler.get_section_sha(section)
353
354
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800355 def _bios_get_sig_sha(self, section):
ctchang38ae4922012-09-03 17:01:16 +0800356 """Get SHA1 hash of firmware vblock in section."""
357 return self._bios_handler.get_section_sig_sha(section)
358
359
Tom Wai-Hong Tam0e680af2011-10-26 14:32:55 +0800360 @allow_multiple_section_input
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800361 def _bios_corrupt_sig(self, section):
Tom Wai-Hong Tam9aea8212011-12-12 15:08:45 +0800362 """Corrupt the requested firmware section signature.
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700363
364 Args:
365 section: A firmware section, either 'a' or 'b'.
366 """
Vic Yang59cac9c2012-05-21 15:28:42 +0800367 self._bios_handler.corrupt_firmware(section)
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700368
369
Tom Wai-Hong Tam0e680af2011-10-26 14:32:55 +0800370 @allow_multiple_section_input
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800371 def _bios_restore_sig(self, section):
Tom Wai-Hong Tam9aea8212011-12-12 15:08:45 +0800372 """Restore the previously corrupted firmware section signature.
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700373
374 Args:
375 section: A firmware section, either 'a' or 'b'.
376 """
Vic Yang59cac9c2012-05-21 15:28:42 +0800377 self._bios_handler.restore_firmware(section)
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700378
379
Tom Wai-Hong Tamcfda61f2011-11-02 17:41:01 +0800380 @allow_multiple_section_input
Tom Wai-Hong Tamc1a569f2012-12-04 15:07:25 +0800381 def _bios_corrupt_body(self, section):
382 """Corrupt the requested firmware section body.
383
384 Args:
385 section: A firmware section, either 'a' or 'b'.
386 """
387 self._bios_handler.corrupt_firmware_body(section)
388
389
390 @allow_multiple_section_input
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800391 def _bios_restore_body(self, section):
Tom Wai-Hong Tam81f70002011-12-13 12:29:46 +0800392 """Restore the previously corrupted firmware section body.
393
394 Args:
395 section: A firmware section, either 'a' or 'b'.
396 """
Vic Yang59cac9c2012-05-21 15:28:42 +0800397 self._bios_handler.restore_firmware_body(section)
Tom Wai-Hong Tam81f70002011-12-13 12:29:46 +0800398
399
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800400 def __bios_modify_version(self, section, delta):
Tom Wai-Hong Tam46d03b12012-02-08 12:02:17 +0800401 """Modify firmware version for the requested section, by adding delta.
402
403 The passed in delta, a positive or a negative number, is added to the
404 original firmware version.
405 """
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800406 original_version = self._bios_get_version(section)
Tom Wai-Hong Tam46d03b12012-02-08 12:02:17 +0800407 new_version = original_version + delta
Vic Yang59cac9c2012-05-21 15:28:42 +0800408 flags = self._bios_handler.get_section_flags(section)
Tom Wai-Hong Tam46d03b12012-02-08 12:02:17 +0800409 self._chromeos_interface.log(
410 'Setting firmware section %s version from %d to %d' % (
411 section, original_version, new_version))
Vic Yang59cac9c2012-05-21 15:28:42 +0800412 self._bios_handler.set_section_version(section, new_version, flags,
413 write_through=True)
Tom Wai-Hong Tam46d03b12012-02-08 12:02:17 +0800414
Tom Wai-Hong Tamc1a569f2012-12-04 15:07:25 +0800415
Tom Wai-Hong Tam46d03b12012-02-08 12:02:17 +0800416 @allow_multiple_section_input
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800417 def _bios_move_version_backward(self, section):
Tom Wai-Hong Tam46d03b12012-02-08 12:02:17 +0800418 """Decrement firmware version for the requested section."""
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800419 self.__bios_modify_version(section, -1)
Tom Wai-Hong Tam46d03b12012-02-08 12:02:17 +0800420
421
422 @allow_multiple_section_input
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800423 def _bios_move_version_forward(self, section):
Tom Wai-Hong Tam46d03b12012-02-08 12:02:17 +0800424 """Increase firmware version for the requested section."""
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800425 self.__bios_modify_version(section, 1)
Tom Wai-Hong Tam46d03b12012-02-08 12:02:17 +0800426
Tom Wai-Hong Tamc1a569f2012-12-04 15:07:25 +0800427
428 def _bios_get_version(self, section):
429 """Retrieve firmware version of a section."""
430 return self._bios_handler.get_section_version(section)
431
432
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800433 def _bios_get_datakey_version(self, section):
ctchangc7e55ea2012-08-09 16:19:14 +0800434 """Return firmware data key version."""
435 return self._bios_handler.get_section_datakey_version(section)
436
Chun-ting Changa4f65532012-10-17 16:57:28 +0800437
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800438 def _bios_get_kernel_subkey_version(self,section):
ctchangc7e55ea2012-08-09 16:19:14 +0800439 """Return kernel subkey version."""
440 return self._bios_handler.get_section_kernel_subkey_version(section)
Tom Wai-Hong Tam46d03b12012-02-08 12:02:17 +0800441
Tom Wai-Hong Tam0a7b2be2012-10-15 16:44:12 +0800442
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800443 def _bios_setup_EC_image(self, ec_path):
Tom Wai-Hong Tam23870e02012-08-24 16:15:34 +0800444 """Setup the new EC image for later update.
445
446 Args:
447 ec_path: The path of the EC image to be updated.
448 """
449 self._ec_image = flashrom_handler.FlashromHandler()
450 self._ec_image.init(saft_flashrom_util,
451 self._chromeos_interface,
452 'ec_root_key.vpubk',
453 '/usr/share/vboot/devkeys',
454 'ec')
455 self._ec_image.new_image(ec_path)
456
457
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800458 def _bios_get_EC_image_sha(self):
Tom Wai-Hong Tam23870e02012-08-24 16:15:34 +0800459 """Get SHA1 hash of RW firmware section of the EC autest image."""
460 return self._ec_image.get_section_sha('rw')
461
462
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800463 def _bios_update_EC_from_image(self, section, flags):
Tom Wai-Hong Tam23870e02012-08-24 16:15:34 +0800464 """Update EC via software sync design.
465
466 It copys the RW section from the EC image, which is loaded by calling
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800467 bios_setup_EC_image(), to the EC area of the specified RW section on the
Tom Wai-Hong Tam23870e02012-08-24 16:15:34 +0800468 current AP firmware.
469
470 Args:
471 section: A firmware section on current BIOS, either 'a' or 'b'.
472 flags: An integer of preamble flags.
473 """
474 blob = self._ec_image.get_section_body('rw')
475 self._bios_handler.set_section_ecbin(section, blob,
476 write_through=True)
Chun-ting Chang708a2762012-12-10 12:25:13 +0800477 self._bios_set_preamble_flags(section, flags)
Tom Wai-Hong Tam23870e02012-08-24 16:15:34 +0800478
479
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800480 def _bios_dump_whole(self, bios_path):
Tom Wai-Hong Tamb63bc742012-08-30 20:41:30 +0800481 """Dump the current BIOS firmware to a file, specified by bios_path.
482
483 Args:
484 bios_path: The path of the BIOS image to be written.
485 """
486 self._bios_handler.dump_whole(bios_path)
487
488
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800489 def _bios_dump_rw(self, dir_path):
ctchang38ae4922012-09-03 17:01:16 +0800490 """Dump the current BIOS firmware RW to dir_path.
491
492 VBOOTA, VBOOTB, FVMAIN, FVMAINB need to be dumped.
493
494 Args:
495 dir_path: The path of directory which contains files to be written.
496 """
497 if not os.path.isdir(dir_path):
498 raise Exception("%s doesn't exist" % dir_path)
499
500 VBOOTA_blob = self._bios_handler.get_section_sig('a')
501 VBOOTB_blob = self._bios_handler.get_section_sig('b')
502 FVMAIN_blob = self._bios_handler.get_section_body('a')
503 FVMAINB_blob = self._bios_handler.get_section_body('b')
504
505 open(os.path.join(dir_path, 'VBOOTA'), 'w').write(VBOOTA_blob)
506 open(os.path.join(dir_path, 'VBOOTB'), 'w').write(VBOOTB_blob)
507 open(os.path.join(dir_path, 'FVMAIN'), 'w').write(FVMAIN_blob)
508 open(os.path.join(dir_path, 'FVMAINB'), 'w').write(FVMAINB_blob)
509
510
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800511 def _bios_write_whole(self, bios_path):
Tom Wai-Hong Tamb63bc742012-08-30 20:41:30 +0800512 """Write the firmware from bios_path to the current system.
513
514 Args:
515 bios_path: The path of the source BIOS image.
516 """
517 self._bios_handler.new_image(bios_path)
518 self._bios_handler.write_whole()
519
520
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800521 def _bios_write_rw(self, dir_path):
ctchang38ae4922012-09-03 17:01:16 +0800522 """Write the firmware RW from dir_path to the current system.
523
524 VBOOTA, VBOOTB, FVMAIN, FVMAINB need to be written.
525
526 Args:
527 dir_path: The path of directory which contains the source files.
528 """
529 if not os.path.exists(os.path.join(dir_path, 'VBOOTA')) or \
530 not os.path.exists(os.path.join(dir_path, 'VBOOTB')) or \
531 not os.path.exists(os.path.join(dir_path, 'FVMAIN')) or \
532 not os.path.exists(os.path.join(dir_path, 'FVMAINB')):
533 raise Exception("Source firmware file(s) doesn't exist.")
534
535 VBOOTA_blob = open(os.path.join(dir_path, 'VBOOTA'), 'rb').read()
536 VBOOTB_blob = open(os.path.join(dir_path, 'VBOOTB'), 'rb').read()
537 FVMAIN_blob = open(os.path.join(dir_path, 'FVMAIN'), 'rb').read()
538 FVMAINB_blob = open(os.path.join(dir_path, 'FVMAINB'), 'rb').read()
539
540 self._bios_handler.set_section_sig('a', VBOOTA_blob,
541 write_through=True)
542 self._bios_handler.set_section_sig('b', VBOOTB_blob,
543 write_through=True)
544 self._bios_handler.set_section_body('a', FVMAIN_blob,
545 write_through=True)
546 self._bios_handler.set_section_body('b', FVMAINB_blob,
547 write_through=True)
548
549
Tom Wai-Hong Tamc1a569f2012-12-04 15:07:25 +0800550 def _ec_get_version(self):
551 """Get EC version via mosys.
552
553 Returns:
554 A string of the EC version.
555 """
556 return self._chromeos_interface.run_shell_command_get_output(
557 'mosys ec info | sed "s/.*| //"')[0]
558
559
560 def _ec_get_firmware_sha(self):
561 """Get SHA1 hash of EC RW firmware section."""
562 return self._ec_handler.get_section_sha('rw')
563
564
565 @allow_multiple_section_input
566 def _ec_corrupt_sig(self, section):
567 """Corrupt the requested EC section signature.
568
569 Args:
570 section: A EC section, either 'a' or 'b'.
571 """
572 self._ec_handler.corrupt_firmware(section, corrupt_all=True)
573
574
575 @allow_multiple_section_input
576 def _ec_restore_sig(self, section):
577 """Restore the previously corrupted EC section signature.
578
579 Args:
580 section: An EC section, either 'a' or 'b'.
581 """
582 self._ec_handler.restore_firmware(section, restore_all=True)
583
584
585 @allow_multiple_section_input
586 def _ec_corrupt_body(self, section):
587 """Corrupt the requested EC section body.
588
589 Args:
590 section: An EC section, either 'a' or 'b'.
591 """
592 self._ec_handler.corrupt_firmware_body(section, corrupt_all=True)
593
594
595 @allow_multiple_section_input
596 def _ec_restore_body(self, section):
597 """Restore the previously corrupted EC section body.
598
599 Args:
600 section: An EC section, either 'a' or 'b'.
601 """
602 self._ec_handler.restore_firmware_body(section, restore_all=True)
603
604
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800605 def _ec_dump_firmware(self, ec_path):
Tom Wai-Hong Tam23870e02012-08-24 16:15:34 +0800606 """Dump the current EC firmware to a file, specified by ec_path.
607
608 Args:
609 ec_path: The path of the EC image to be written.
610 """
611 self._ec_handler.dump_whole(ec_path)
612
613
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800614 def _ec_set_write_protect(self, enable):
Tom Wai-Hong Tam44204b32012-11-20 13:55:40 +0800615 """Enable write protect of the EC flash chip.
616
617 Args:
618 enable: True if activating EC write protect. Otherwise, False.
619 """
Tom Wai-Hong Tam44204b32012-11-20 13:55:40 +0800620 if enable:
621 self._ec_handler.enable_write_protect()
622 else:
623 self._ec_handler.disable_write_protect()
624
625
Tom Wai-Hong Tamc1a569f2012-12-04 15:07:25 +0800626 @allow_multiple_section_input
627 def _kernel_corrupt_sig(self, section):
628 """Corrupt the requested kernel section.
629
630 Args:
631 section: A kernel section, either 'a' or 'b'.
632 """
633 self._kernel_handler.corrupt_kernel(section)
634
635
636 @allow_multiple_section_input
637 def _kernel_restore_sig(self, section):
638 """Restore the requested kernel section (previously corrupted).
639
640 Args:
641 section: A kernel section, either 'a' or 'b'.
642 """
643 self._kernel_handler.restore_kernel(section)
644
645
646 def __kernel_modify_version(self, section, delta):
647 """Modify kernel version for the requested section, by adding delta.
648
649 The passed in delta, a positive or a negative number, is added to the
650 original kernel version.
651 """
652 original_version = self._kernel_handler.get_version(section)
653 new_version = original_version + delta
654 self._chromeos_interface.log(
655 'Setting kernel section %s version from %d to %d' % (
656 section, original_version, new_version))
657 self._kernel_handler.set_version(section, new_version)
658
659
660 @allow_multiple_section_input
661 def _kernel_move_version_backward(self, section):
662 """Decrement kernel version for the requested section."""
663 self.__kernel_modify_version(section, -1)
664
665
666 @allow_multiple_section_input
667 def _kernel_move_version_forward(self, section):
668 """Increase kernel version for the requested section."""
669 self.__kernel_modify_version(section, 1)
670
671
672 def _kernel_get_version(self, section):
673 """Return kernel version."""
674 return self._kernel_handler.get_version(section)
675
676
677 def _kernel_get_datakey_version(self, section):
678 """Return kernel datakey version."""
679 return self._kernel_handler.get_datakey_version(section)
680
681
682 def _kernel_diff_a_b(self):
683 """Compare kernel A with B.
684
685 Returns:
686 True: if kernel A is different with B.
687 False: if kernel A is the same as B.
688 """
689 rootdev = self._chromeos_interface.get_root_dev()
690 kernel_a = self._chromeos_interface.join_part(rootdev, '3')
691 kernel_b = self._chromeos_interface.join_part(rootdev, '5')
692
693 # The signature (some kind of hash) for the kernel body is stored in
694 # the beginning. So compare the first 64KB (including header, preamble,
695 # and signature) should be enough to check them identical.
696 header_a = self._chromeos_interface.read_partition(kernel_a, 0x10000)
697 header_b = self._chromeos_interface.read_partition(kernel_b, 0x10000)
698
699 return header_a != header_b
700
701
702 def _kernel_resign_with_keys(self, section, key_path=None):
703 """Resign kernel with temporary key."""
704 self._kernel_handler.resign_kernel(section, key_path)
705
706
707 def _tpm_get_firmware_version(self):
708 """Retrieve tpm firmware body version."""
709 return self._tpm_handler.get_fw_version()
710
711
712 def _tpm_get_firmware_datakey_version(self):
713 """Retrieve tpm firmware data key version."""
714 return self._tpm_handler.get_fw_body_version()
715
716
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800717 def _cgpt_run_test_loop(self):
Tom Wai-Hong Tam48958832011-12-30 10:16:57 +0800718 """Run the CgptState test loop. The tst logic is handled in the client.
719
720 Returns:
721 0: there are more cgpt tests to execute.
722 1: no more CgptState test, finished.
723 """
724 return self._cgpt_state.test_loop()
725
726
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800727 def _cgpt_set_test_step(self, step):
Tom Wai-Hong Tam48958832011-12-30 10:16:57 +0800728 """Set the CgptState test step.
729
730 Args:
731 step: A test step number.
732 """
733 self._cgpt_state.set_step(step)
734
735
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800736 def _cgpt_get_test_step(self):
Tom Wai-Hong Tam48958832011-12-30 10:16:57 +0800737 """Get the CgptState test step.
738
739 Returns:
740 A test step number.
741 """
742 return self._cgpt_state.get_step()
743
744
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800745 def _updater_setup(self, shellball=None):
Chun-ting Changcf924e92012-10-29 13:49:01 +0800746 """Setup the updater.
747
748 Args:
749 shellball: Path of provided shellball. Use default shellball
750 if None,
751 """
752 self._updater.setup(self._chromeos_interface, shellball)
753
754
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800755 def _updater_cleanup(self):
Chun-ting Changcf924e92012-10-29 13:49:01 +0800756 self._updater.cleanup_temp_dir()
757
758
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800759 def _updater_get_fwid(self):
Chun-ting Changcf924e92012-10-29 13:49:01 +0800760 """Retrieve shellball's fwid.
761
762 This method should be called after updater_setup.
763
764 Returns:
765 Shellball's fwid.
766 """
767 return self._updater.retrieve_fwid()
768
769
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800770 def _updater_resign_firmware(self, version):
Chun-ting Changcf924e92012-10-29 13:49:01 +0800771 """Resign firmware with version.
772
773 Args:
774 version: new version number.
775 """
776 self._updater.resign_firmware(version)
777
778
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800779 def _updater_repack_shellball(self, append):
Chun-ting Changcf924e92012-10-29 13:49:01 +0800780 """Repack shellball with new fwid.
781
782 Args:
783 append: use for new fwid naming.
784 """
785 self._updater.repack_shellball(append)
786
787
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800788 def _updater_run_autoupdate(self, append):
Chun-ting Changcf924e92012-10-29 13:49:01 +0800789 """Run chromeos-firmwareupdate with autoupdate mode."""
790 options = ['--noupdate_ec', '--nocheck_rw_compatible']
791 self._updater.run_firmwareupdate(mode='autoupdate',
792 updater_append=append,
793 options=options)
794
795
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800796 def _updater_run_factory_install(self):
Chun-ting Changcf924e92012-10-29 13:49:01 +0800797 """Run chromeos-firmwareupdate with factory_install mode."""
798 options = ['--noupdate_ec']
799 self._updater.run_firmwareupdate(mode='factory_install',
800 options=options)
801
802
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800803 def _updater_run_bootok(self, append):
Chun-ting Changcf924e92012-10-29 13:49:01 +0800804 """Run chromeos-firmwareupdate with bootok mode."""
805 self._updater.run_firmwareupdate(mode='bootok',
806 updater_append=append)
807
808
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800809 def _updater_run_recovery(self):
Chun-ting Changcf924e92012-10-29 13:49:01 +0800810 """Run chromeos-firmwareupdate with recovery mode."""
811 options = ['--noupdate_ec', '--nocheck_rw_compatible']
812 self._updater.run_firmwareupdate(mode='recovery',
813 options=options)
814
815
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800816 def _updater_get_temp_path(self):
Chun-ting Changcf924e92012-10-29 13:49:01 +0800817 """Get updater's temp directory path."""
818 return self._updater.get_temp_path()
819
820
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800821 def _updater_get_keys_path(self):
Chun-ting Changcf924e92012-10-29 13:49:01 +0800822 """Get updater's keys directory path."""
823 return self._updater.get_keys_path()
824
825
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800826 def _updater_get_work_path(self):
Chun-ting Changcf924e92012-10-29 13:49:01 +0800827 """Get updater's work directory path."""
828 return self._updater.get_work_path()
829
830
Tom Wai-Hong Tambea57b32011-09-02 18:27:47 +0800831 def cleanup(self):
832 """Cleanup for the RPC server. Currently nothing."""
833 pass
834
835
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700836def main():
837 parser = OptionParser(usage='Usage: %prog [options]')
838 parser.add_option('--port', type='int', dest='port', default=9990,
839 help='port number of XMLRPC server')
840 (options, args) = parser.parse_args()
841
842 faft_client = FAFTClient()
843
844 # Launch the XMLRPC server to provide FAFTClient commands.
Tom Wai-Hong Tam4a257e52011-11-12 08:36:22 +0800845 server = SimpleXMLRPCServer(('localhost', options.port), allow_none=True,
Tom Wai-Hong Tamc1e0b9a2012-11-01 13:52:39 +0800846 logRequests=True)
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700847 server.register_introspection_functions()
848 server.register_instance(faft_client)
849 print 'XMLRPC Server: Serving FAFTClient on port %s' % options.port
850 server.serve_forever()
851
852
853if __name__ == '__main__':
854 main()