blob: 3fe37c89d8c3bb6486958009bf86896815d726d9 [file] [log] [blame]
barfab@chromium.orgb6d29932012-04-11 09:46:43 +02001# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -07002# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5"""Exposes the FAFTClient interface over XMLRPC.
6
7It launches a XMLRPC server and exposes the interface of FAFTClient object.
8The FAFTClient object aggreates some useful functions of exisintg SAFT
9libraries.
10"""
11
barfab@chromium.orgb6d29932012-04-11 09:46:43 +020012import functools, os, shutil, sys
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -070013from optparse import OptionParser
14from SimpleXMLRPCServer import SimpleXMLRPCServer
15
16# Import libraries from SAFT.
Tom Wai-Hong Tamc1576b72011-11-08 11:36:16 +080017sys.path.append('/usr/local/sbin/firmware/saft')
barfab@chromium.orgb6d29932012-04-11 09:46:43 +020018import cgpt_state, chromeos_interface, flashrom_handler, kernel_handler
19import saft_flashrom_util, tpm_handler
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
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -070033class FAFTClient(object):
34 """A class of FAFT client which aggregates some useful functions of SAFT.
35
36 This class can be exposed via a XMLRPC server such that its functions can
37 be accessed remotely.
38
39 Attributes:
40 _chromeos_interface: An object to encapsulate OS services functions.
Vic Yang59cac9c2012-05-21 15:28:42 +080041 _bios_handler: An object to automate BIOS flashrom testing.
42 _ec_handler: An object to automate EC flashrom testing.
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -070043 _kernel_handler: An object to provide kernel related actions.
44 _tpm_handler: An object to control TPM device.
45 """
46
47 def __init__(self):
48 """Initialize the data attributes of this class."""
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -070049 # TODO(waihong): Move the explicit object.init() methods to the
50 # objects' constructors (ChromeOSInterface, FlashromHandler,
51 # KernelHandler, and TpmHandler).
52 self._chromeos_interface = chromeos_interface.ChromeOSInterface(False)
Tom Wai-Hong Tam48958832011-12-30 10:16:57 +080053 # We keep the state of FAFT test in a permanent directory over reboots.
Tom Wai-Hong Tam07278c22012-02-08 16:53:00 +080054 state_dir = '/var/tmp/faft'
55 self._chromeos_interface.init(state_dir, log_file='/tmp/faft_log.txt')
56 os.chdir(state_dir)
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -070057
Vic Yang59cac9c2012-05-21 15:28:42 +080058 self._bios_handler = flashrom_handler.FlashromHandler()
59 self._bios_handler.init(saft_flashrom_util,
60 self._chromeos_interface,
61 None,
62 '/usr/share/vboot/devkeys',
63 'bios')
64 self._bios_handler.new_image()
65
Todd Brochf2b1d012012-06-14 12:55:21 -070066 self._ec_handler = None
67 if not os.system("mosys ec info"):
68 self._ec_handler = flashrom_handler.FlashromHandler()
69 self._ec_handler.init(saft_flashrom_util,
70 self._chromeos_interface,
71 'ec_root_key.vbpubk',
72 '/usr/share/vboot/devkeys',
73 'ec')
74 self._ec_handler.new_image()
75
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -070076
77 self._kernel_handler = kernel_handler.KernelHandler()
Tom Wai-Hong Tam07278c22012-02-08 16:53:00 +080078 # TODO(waihong): The dev_key_path is a new argument. We do that in
79 # order not to break the old image and still be able to run.
80 try:
81 self._kernel_handler.init(self._chromeos_interface,
82 dev_key_path='/usr/share/vboot/devkeys')
83 except:
84 # Copy the key to the current working directory.
85 shutil.copy('/usr/share/vboot/devkeys/kernel_data_key.vbprivk', '.')
86 self._kernel_handler.init(self._chromeos_interface)
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -070087
88 self._tpm_handler = tpm_handler.TpmHandler()
89 self._tpm_handler.init(self._chromeos_interface)
90
Tom Wai-Hong Tam48958832011-12-30 10:16:57 +080091 self._cgpt_state = cgpt_state.CgptState(
92 'AUTO', self._chromeos_interface, self.get_root_dev())
93
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -070094
Tom Wai-Hong Tame8f291a2011-12-08 22:03:53 +080095 def _dispatch(self, method, params):
96 """This _dispatch method handles string conversion especially.
97
98 Since we turn off allow_dotted_names option. So any string conversion,
99 like str(FAFTClient.method), i.e. FAFTClient.method.__str__, failed
100 via XML RPC call.
101 """
102 is_str = method.endswith('.__str__')
103 if is_str:
104 method = method.rsplit('.', 1)[0]
105 try:
106 func = getattr(self, method)
107 except AttributeError:
108 raise Exception('method "%s" is not supported' % method)
109 else:
110 if is_str:
111 return str(func)
112 else:
113 return func(*params)
114
115
Tom Wai-Hong Tambea57b32011-09-02 18:27:47 +0800116 def is_available(self):
117 """Function for polling the RPC server availability.
118
119 Returns:
120 Always True.
121 """
122 return True
123
124
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700125 def run_shell_command(self, command):
126 """Run shell command.
127
128 Args:
129 command: A shell command to be run.
130 """
131 self._chromeos_interface.log('Requesting run shell command')
132 self._chromeos_interface.run_shell_command(command)
133
134
135 def run_shell_command_get_output(self, command):
136 """Run shell command and get its console output.
137
138 Args:
139 command: A shell command to be run.
140
141 Returns:
142 A list of strings stripped of the newline characters.
143 """
144 self._chromeos_interface.log(
145 'Requesting run shell command and get its console output')
146 return self._chromeos_interface.run_shell_command_get_output(command)
147
148
149 def software_reboot(self):
150 """Request software reboot."""
151 self._chromeos_interface.log('Requesting software reboot')
152 self._chromeos_interface.run_shell_command('reboot')
153
154
Tom Wai-Hong Tam678ab152011-12-14 15:27:24 +0800155 def get_platform_name(self):
156 """Get the platform name of the current system.
157
158 Returns:
159 A string of the platform name.
160 """
161 self._chromeos_interface.log('Requesting get platform name')
162 return self._chromeos_interface.run_shell_command_get_output(
163 'mosys platform name')[0]
164
165
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700166 def get_crossystem_value(self, key):
167 """Get crossystem value of the requested key.
168
169 Args:
170 key: A crossystem key.
171
172 Returns:
173 A string of the requested crossystem value.
174 """
175 self._chromeos_interface.log('Requesting get crossystem value')
176 return self._chromeos_interface.run_shell_command_get_output(
177 'crossystem %s' % key)[0]
178
179
Tom Wai-Hong Tamcfda61f2011-11-02 17:41:01 +0800180 def get_root_dev(self):
181 """Get the name of root device without partition number.
182
183 Returns:
184 A string of the root device without partition number.
185 """
186 self._chromeos_interface.log('Requesting get root device')
187 return self._chromeos_interface.get_root_dev()
188
189
190 def get_root_part(self):
191 """Get the name of root device with partition number.
192
193 Returns:
194 A string of the root device with partition number.
195 """
196 self._chromeos_interface.log('Requesting get root part')
197 return self._chromeos_interface.get_root_part()
198
199
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700200 def set_try_fw_b(self):
201 """Set 'Try Frimware B' flag in crossystem."""
202 self._chromeos_interface.log('Requesting restart with firmware B')
203 self._chromeos_interface.cs.fwb_tries = 1
204
205
Tom Wai-Hong Tam76c75072011-10-25 18:00:12 +0800206 def request_recovery_boot(self):
207 """Request running in recovery mode on the restart."""
208 self._chromeos_interface.log('Requesting restart in recovery mode')
209 self._chromeos_interface.cs.request_recovery()
210
211
Tom Wai-Hong Tam8c9eed62011-12-28 15:05:05 +0800212 def get_gbb_flags(self):
213 """Get the GBB flags.
214
215 Returns:
216 An integer of the GBB flags.
217 """
218 self._chromeos_interface.log('Getting GBB flags')
Vic Yang59cac9c2012-05-21 15:28:42 +0800219 return self._bios_handler.get_gbb_flags()
Tom Wai-Hong Tam8c9eed62011-12-28 15:05:05 +0800220
221
Tom Wai-Hong Tam81f70002011-12-13 12:29:46 +0800222 def get_firmware_flags(self, section):
223 """Get the preamble flags of a firmware section.
224
225 Args:
226 section: A firmware section, either 'a' or 'b'.
227
228 Returns:
229 An integer of the preamble flags.
230 """
231 self._chromeos_interface.log('Getting preamble flags of firmware %s' %
232 section)
Vic Yang59cac9c2012-05-21 15:28:42 +0800233 return self._bios_handler.get_section_flags(section)
234
235
236 @allow_multiple_section_input
237 def corrupt_EC(self, section):
238 """Corrupt the requested EC section signature.
239
240 Args:
241 section: A EC section, either 'a' or 'b'.
242 """
243 self._chromeos_interface.log('Corrupting EC signature %s' %
244 section)
245 self._ec_handler.corrupt_firmware(section)
246
247
248 @allow_multiple_section_input
249 def corrupt_EC_body(self, section):
250 """Corrupt the requested EC section body.
251
252 Args:
253 section: An EC section, either 'a' or 'b'.
254 """
255 self._chromeos_interface.log('Corrupting EC body %s' %
256 section)
257 self._ec_handler.corrupt_firmware_body(section)
258
259
260 @allow_multiple_section_input
261 def restore_EC(self, section):
262 """Restore the previously corrupted EC section signature.
263
264 Args:
265 section: An EC section, either 'a' or 'b'.
266 """
267 self._chromeos_interface.log('Restoring EC signature %s' %
268 section)
269 self._ec_handler.restore_firmware(section)
270
271
272 @allow_multiple_section_input
273 def restore_EC_body(self, section):
274 """Restore the previously corrupted EC section body.
275
276 Args:
277 section: An EC section, either 'a' or 'b'.
278 """
279 self._chromeos_interface.log('Restoring EC body %s' %
280 section)
281 self._ec_handler.restore_firmware_body(section)
Tom Wai-Hong Tam81f70002011-12-13 12:29:46 +0800282
283
Tom Wai-Hong Tam0e680af2011-10-26 14:32:55 +0800284 @allow_multiple_section_input
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700285 def corrupt_firmware(self, section):
Tom Wai-Hong Tam9aea8212011-12-12 15:08:45 +0800286 """Corrupt the requested firmware section signature.
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700287
288 Args:
289 section: A firmware section, either 'a' or 'b'.
290 """
Tom Wai-Hong Tam9aea8212011-12-12 15:08:45 +0800291 self._chromeos_interface.log('Corrupting firmware signature %s' %
292 section)
Vic Yang59cac9c2012-05-21 15:28:42 +0800293 self._bios_handler.corrupt_firmware(section)
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700294
295
Tom Wai-Hong Tam0e680af2011-10-26 14:32:55 +0800296 @allow_multiple_section_input
Tom Wai-Hong Tam81f70002011-12-13 12:29:46 +0800297 def corrupt_firmware_body(self, section):
298 """Corrupt the requested firmware section body.
299
300 Args:
301 section: A firmware section, either 'a' or 'b'.
302 """
303 self._chromeos_interface.log('Corrupting firmware body %s' %
304 section)
Vic Yang59cac9c2012-05-21 15:28:42 +0800305 self._bios_handler.corrupt_firmware_body(section)
Tom Wai-Hong Tam81f70002011-12-13 12:29:46 +0800306
307
308 @allow_multiple_section_input
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700309 def restore_firmware(self, section):
Tom Wai-Hong Tam9aea8212011-12-12 15:08:45 +0800310 """Restore the previously corrupted firmware section signature.
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700311
312 Args:
313 section: A firmware section, either 'a' or 'b'.
314 """
Tom Wai-Hong Tam9aea8212011-12-12 15:08:45 +0800315 self._chromeos_interface.log('Restoring firmware signature %s' %
316 section)
Vic Yang59cac9c2012-05-21 15:28:42 +0800317 self._bios_handler.restore_firmware(section)
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700318
319
Tom Wai-Hong Tamcfda61f2011-11-02 17:41:01 +0800320 @allow_multiple_section_input
Tom Wai-Hong Tam81f70002011-12-13 12:29:46 +0800321 def restore_firmware_body(self, section):
322 """Restore the previously corrupted firmware section body.
323
324 Args:
325 section: A firmware section, either 'a' or 'b'.
326 """
327 self._chromeos_interface.log('Restoring firmware body %s' %
328 section)
Vic Yang59cac9c2012-05-21 15:28:42 +0800329 self._bios_handler.restore_firmware_body(section)
Tom Wai-Hong Tam81f70002011-12-13 12:29:46 +0800330
331
Tom Wai-Hong Tam46d03b12012-02-08 12:02:17 +0800332 def _modify_firmware_version(self, section, delta):
333 """Modify firmware version for the requested section, by adding delta.
334
335 The passed in delta, a positive or a negative number, is added to the
336 original firmware version.
337 """
Vic Yang59cac9c2012-05-21 15:28:42 +0800338 original_version = self._bios_handler.get_section_version(section)
Tom Wai-Hong Tam46d03b12012-02-08 12:02:17 +0800339 new_version = original_version + delta
Vic Yang59cac9c2012-05-21 15:28:42 +0800340 flags = self._bios_handler.get_section_flags(section)
Tom Wai-Hong Tam46d03b12012-02-08 12:02:17 +0800341 self._chromeos_interface.log(
342 'Setting firmware section %s version from %d to %d' % (
343 section, original_version, new_version))
Vic Yang59cac9c2012-05-21 15:28:42 +0800344 self._bios_handler.set_section_version(section, new_version, flags,
345 write_through=True)
Tom Wai-Hong Tam46d03b12012-02-08 12:02:17 +0800346
347 @allow_multiple_section_input
348 def move_firmware_backward(self, section):
349 """Decrement firmware version for the requested section."""
350 self._modify_firmware_version(section, -1)
351
352
353 @allow_multiple_section_input
354 def move_firmware_forward(self, section):
355 """Increase firmware version for the requested section."""
356 self._modify_firmware_version(section, 1)
357
358
Tom Wai-Hong Tam81f70002011-12-13 12:29:46 +0800359 @allow_multiple_section_input
Tom Wai-Hong Tamcfda61f2011-11-02 17:41:01 +0800360 def corrupt_kernel(self, section):
361 """Corrupt the requested kernel section.
362
363 Args:
364 section: A kernel section, either 'a' or 'b'.
365 """
366 self._chromeos_interface.log('Corrupting kernel %s' % section)
367 self._kernel_handler.corrupt_kernel(section)
368
369
370 @allow_multiple_section_input
371 def restore_kernel(self, section):
372 """Restore the requested kernel section (previously corrupted).
373
374 Args:
375 section: A kernel section, either 'a' or 'b'.
376 """
377 self._chromeos_interface.log('restoring kernel %s' % section)
378 self._kernel_handler.restore_kernel(section)
379
380
Tom Wai-Hong Tam07278c22012-02-08 16:53:00 +0800381 def _modify_kernel_version(self, section, delta):
382 """Modify kernel version for the requested section, by adding delta.
383
384 The passed in delta, a positive or a negative number, is added to the
385 original kernel version.
386 """
387 original_version = self._kernel_handler.get_version(section)
388 new_version = original_version + delta
389 self._chromeos_interface.log(
390 'Setting kernel section %s version from %d to %d' % (
391 section, original_version, new_version))
392 self._kernel_handler.set_version(section, new_version)
393
394
395 @allow_multiple_section_input
396 def move_kernel_backward(self, section):
397 """Decrement kernel version for the requested section."""
398 self._modify_kernel_version(section, -1)
399
400
401 @allow_multiple_section_input
402 def move_kernel_forward(self, section):
403 """Increase kernel version for the requested section."""
404 self._modify_kernel_version(section, 1)
405
406
Tom Wai-Hong Tam48958832011-12-30 10:16:57 +0800407 def run_cgpt_test_loop(self):
408 """Run the CgptState test loop. The tst logic is handled in the client.
409
410 Returns:
411 0: there are more cgpt tests to execute.
412 1: no more CgptState test, finished.
413 """
414 return self._cgpt_state.test_loop()
415
416
417 def set_cgpt_test_step(self, step):
418 """Set the CgptState test step.
419
420 Args:
421 step: A test step number.
422 """
423 self._cgpt_state.set_step(step)
424
425
426 def get_cgpt_test_step(self):
427 """Get the CgptState test step.
428
429 Returns:
430 A test step number.
431 """
432 return self._cgpt_state.get_step()
433
434
Tom Wai-Hong Tambea57b32011-09-02 18:27:47 +0800435 def cleanup(self):
436 """Cleanup for the RPC server. Currently nothing."""
437 pass
438
439
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700440def main():
441 parser = OptionParser(usage='Usage: %prog [options]')
442 parser.add_option('--port', type='int', dest='port', default=9990,
443 help='port number of XMLRPC server')
444 (options, args) = parser.parse_args()
445
446 faft_client = FAFTClient()
447
448 # Launch the XMLRPC server to provide FAFTClient commands.
Tom Wai-Hong Tam4a257e52011-11-12 08:36:22 +0800449 server = SimpleXMLRPCServer(('localhost', options.port), allow_none=True,
450 logRequests=False)
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700451 server.register_introspection_functions()
452 server.register_instance(faft_client)
453 print 'XMLRPC Server: Serving FAFTClient on port %s' % options.port
454 server.serve_forever()
455
456
457if __name__ == '__main__':
458 main()