blob: ed15d107a754c614b491a0af841ab12b79f5f4bf [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
66 self._ec_handler = flashrom_handler.FlashromHandler()
67 self._ec_handler.init(saft_flashrom_util,
68 self._chromeos_interface,
69 'ec_root_key.vbpubk',
70 '/usr/share/vboot/devkeys',
71 'ec')
72 self._ec_handler.new_image()
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -070073
74 self._kernel_handler = kernel_handler.KernelHandler()
Tom Wai-Hong Tam07278c22012-02-08 16:53:00 +080075 # TODO(waihong): The dev_key_path is a new argument. We do that in
76 # order not to break the old image and still be able to run.
77 try:
78 self._kernel_handler.init(self._chromeos_interface,
79 dev_key_path='/usr/share/vboot/devkeys')
80 except:
81 # Copy the key to the current working directory.
82 shutil.copy('/usr/share/vboot/devkeys/kernel_data_key.vbprivk', '.')
83 self._kernel_handler.init(self._chromeos_interface)
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -070084
85 self._tpm_handler = tpm_handler.TpmHandler()
86 self._tpm_handler.init(self._chromeos_interface)
87
Tom Wai-Hong Tam48958832011-12-30 10:16:57 +080088 self._cgpt_state = cgpt_state.CgptState(
89 'AUTO', self._chromeos_interface, self.get_root_dev())
90
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -070091
Tom Wai-Hong Tame8f291a2011-12-08 22:03:53 +080092 def _dispatch(self, method, params):
93 """This _dispatch method handles string conversion especially.
94
95 Since we turn off allow_dotted_names option. So any string conversion,
96 like str(FAFTClient.method), i.e. FAFTClient.method.__str__, failed
97 via XML RPC call.
98 """
99 is_str = method.endswith('.__str__')
100 if is_str:
101 method = method.rsplit('.', 1)[0]
102 try:
103 func = getattr(self, method)
104 except AttributeError:
105 raise Exception('method "%s" is not supported' % method)
106 else:
107 if is_str:
108 return str(func)
109 else:
110 return func(*params)
111
112
Tom Wai-Hong Tambea57b32011-09-02 18:27:47 +0800113 def is_available(self):
114 """Function for polling the RPC server availability.
115
116 Returns:
117 Always True.
118 """
119 return True
120
121
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700122 def run_shell_command(self, command):
123 """Run shell command.
124
125 Args:
126 command: A shell command to be run.
127 """
128 self._chromeos_interface.log('Requesting run shell command')
129 self._chromeos_interface.run_shell_command(command)
130
131
132 def run_shell_command_get_output(self, command):
133 """Run shell command and get its console output.
134
135 Args:
136 command: A shell command to be run.
137
138 Returns:
139 A list of strings stripped of the newline characters.
140 """
141 self._chromeos_interface.log(
142 'Requesting run shell command and get its console output')
143 return self._chromeos_interface.run_shell_command_get_output(command)
144
145
146 def software_reboot(self):
147 """Request software reboot."""
148 self._chromeos_interface.log('Requesting software reboot')
149 self._chromeos_interface.run_shell_command('reboot')
150
151
Tom Wai-Hong Tam678ab152011-12-14 15:27:24 +0800152 def get_platform_name(self):
153 """Get the platform name of the current system.
154
155 Returns:
156 A string of the platform name.
157 """
158 self._chromeos_interface.log('Requesting get platform name')
159 return self._chromeos_interface.run_shell_command_get_output(
160 'mosys platform name')[0]
161
162
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700163 def get_crossystem_value(self, key):
164 """Get crossystem value of the requested key.
165
166 Args:
167 key: A crossystem key.
168
169 Returns:
170 A string of the requested crossystem value.
171 """
172 self._chromeos_interface.log('Requesting get crossystem value')
173 return self._chromeos_interface.run_shell_command_get_output(
174 'crossystem %s' % key)[0]
175
176
Tom Wai-Hong Tamcfda61f2011-11-02 17:41:01 +0800177 def get_root_dev(self):
178 """Get the name of root device without partition number.
179
180 Returns:
181 A string of the root device without partition number.
182 """
183 self._chromeos_interface.log('Requesting get root device')
184 return self._chromeos_interface.get_root_dev()
185
186
187 def get_root_part(self):
188 """Get the name of root device with partition number.
189
190 Returns:
191 A string of the root device with partition number.
192 """
193 self._chromeos_interface.log('Requesting get root part')
194 return self._chromeos_interface.get_root_part()
195
196
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700197 def set_try_fw_b(self):
198 """Set 'Try Frimware B' flag in crossystem."""
199 self._chromeos_interface.log('Requesting restart with firmware B')
200 self._chromeos_interface.cs.fwb_tries = 1
201
202
Tom Wai-Hong Tam76c75072011-10-25 18:00:12 +0800203 def request_recovery_boot(self):
204 """Request running in recovery mode on the restart."""
205 self._chromeos_interface.log('Requesting restart in recovery mode')
206 self._chromeos_interface.cs.request_recovery()
207
208
Tom Wai-Hong Tam8c9eed62011-12-28 15:05:05 +0800209 def get_gbb_flags(self):
210 """Get the GBB flags.
211
212 Returns:
213 An integer of the GBB flags.
214 """
215 self._chromeos_interface.log('Getting GBB flags')
Vic Yang59cac9c2012-05-21 15:28:42 +0800216 return self._bios_handler.get_gbb_flags()
Tom Wai-Hong Tam8c9eed62011-12-28 15:05:05 +0800217
218
Tom Wai-Hong Tam81f70002011-12-13 12:29:46 +0800219 def get_firmware_flags(self, section):
220 """Get the preamble flags of a firmware section.
221
222 Args:
223 section: A firmware section, either 'a' or 'b'.
224
225 Returns:
226 An integer of the preamble flags.
227 """
228 self._chromeos_interface.log('Getting preamble flags of firmware %s' %
229 section)
Vic Yang59cac9c2012-05-21 15:28:42 +0800230 return self._bios_handler.get_section_flags(section)
231
232
233 @allow_multiple_section_input
234 def corrupt_EC(self, section):
235 """Corrupt the requested EC section signature.
236
237 Args:
238 section: A EC section, either 'a' or 'b'.
239 """
240 self._chromeos_interface.log('Corrupting EC signature %s' %
241 section)
242 self._ec_handler.corrupt_firmware(section)
243
244
245 @allow_multiple_section_input
246 def corrupt_EC_body(self, section):
247 """Corrupt the requested EC section body.
248
249 Args:
250 section: An EC section, either 'a' or 'b'.
251 """
252 self._chromeos_interface.log('Corrupting EC body %s' %
253 section)
254 self._ec_handler.corrupt_firmware_body(section)
255
256
257 @allow_multiple_section_input
258 def restore_EC(self, section):
259 """Restore the previously corrupted EC section signature.
260
261 Args:
262 section: An EC section, either 'a' or 'b'.
263 """
264 self._chromeos_interface.log('Restoring EC signature %s' %
265 section)
266 self._ec_handler.restore_firmware(section)
267
268
269 @allow_multiple_section_input
270 def restore_EC_body(self, section):
271 """Restore the previously corrupted EC section body.
272
273 Args:
274 section: An EC section, either 'a' or 'b'.
275 """
276 self._chromeos_interface.log('Restoring EC body %s' %
277 section)
278 self._ec_handler.restore_firmware_body(section)
Tom Wai-Hong Tam81f70002011-12-13 12:29:46 +0800279
280
Tom Wai-Hong Tam0e680af2011-10-26 14:32:55 +0800281 @allow_multiple_section_input
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700282 def corrupt_firmware(self, section):
Tom Wai-Hong Tam9aea8212011-12-12 15:08:45 +0800283 """Corrupt the requested firmware section signature.
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700284
285 Args:
286 section: A firmware section, either 'a' or 'b'.
287 """
Tom Wai-Hong Tam9aea8212011-12-12 15:08:45 +0800288 self._chromeos_interface.log('Corrupting firmware signature %s' %
289 section)
Vic Yang59cac9c2012-05-21 15:28:42 +0800290 self._bios_handler.corrupt_firmware(section)
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700291
292
Tom Wai-Hong Tam0e680af2011-10-26 14:32:55 +0800293 @allow_multiple_section_input
Tom Wai-Hong Tam81f70002011-12-13 12:29:46 +0800294 def corrupt_firmware_body(self, section):
295 """Corrupt the requested firmware section body.
296
297 Args:
298 section: A firmware section, either 'a' or 'b'.
299 """
300 self._chromeos_interface.log('Corrupting firmware body %s' %
301 section)
Vic Yang59cac9c2012-05-21 15:28:42 +0800302 self._bios_handler.corrupt_firmware_body(section)
Tom Wai-Hong Tam81f70002011-12-13 12:29:46 +0800303
304
305 @allow_multiple_section_input
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700306 def restore_firmware(self, section):
Tom Wai-Hong Tam9aea8212011-12-12 15:08:45 +0800307 """Restore the previously corrupted firmware section signature.
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700308
309 Args:
310 section: A firmware section, either 'a' or 'b'.
311 """
Tom Wai-Hong Tam9aea8212011-12-12 15:08:45 +0800312 self._chromeos_interface.log('Restoring firmware signature %s' %
313 section)
Vic Yang59cac9c2012-05-21 15:28:42 +0800314 self._bios_handler.restore_firmware(section)
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700315
316
Tom Wai-Hong Tamcfda61f2011-11-02 17:41:01 +0800317 @allow_multiple_section_input
Tom Wai-Hong Tam81f70002011-12-13 12:29:46 +0800318 def restore_firmware_body(self, section):
319 """Restore the previously corrupted firmware section body.
320
321 Args:
322 section: A firmware section, either 'a' or 'b'.
323 """
324 self._chromeos_interface.log('Restoring firmware body %s' %
325 section)
Vic Yang59cac9c2012-05-21 15:28:42 +0800326 self._bios_handler.restore_firmware_body(section)
Tom Wai-Hong Tam81f70002011-12-13 12:29:46 +0800327
328
Tom Wai-Hong Tam46d03b12012-02-08 12:02:17 +0800329 def _modify_firmware_version(self, section, delta):
330 """Modify firmware version for the requested section, by adding delta.
331
332 The passed in delta, a positive or a negative number, is added to the
333 original firmware version.
334 """
Vic Yang59cac9c2012-05-21 15:28:42 +0800335 original_version = self._bios_handler.get_section_version(section)
Tom Wai-Hong Tam46d03b12012-02-08 12:02:17 +0800336 new_version = original_version + delta
Vic Yang59cac9c2012-05-21 15:28:42 +0800337 flags = self._bios_handler.get_section_flags(section)
Tom Wai-Hong Tam46d03b12012-02-08 12:02:17 +0800338 self._chromeos_interface.log(
339 'Setting firmware section %s version from %d to %d' % (
340 section, original_version, new_version))
Vic Yang59cac9c2012-05-21 15:28:42 +0800341 self._bios_handler.set_section_version(section, new_version, flags,
342 write_through=True)
Tom Wai-Hong Tam46d03b12012-02-08 12:02:17 +0800343
344 @allow_multiple_section_input
345 def move_firmware_backward(self, section):
346 """Decrement firmware version for the requested section."""
347 self._modify_firmware_version(section, -1)
348
349
350 @allow_multiple_section_input
351 def move_firmware_forward(self, section):
352 """Increase firmware version for the requested section."""
353 self._modify_firmware_version(section, 1)
354
355
Tom Wai-Hong Tam81f70002011-12-13 12:29:46 +0800356 @allow_multiple_section_input
Tom Wai-Hong Tamcfda61f2011-11-02 17:41:01 +0800357 def corrupt_kernel(self, section):
358 """Corrupt the requested kernel section.
359
360 Args:
361 section: A kernel section, either 'a' or 'b'.
362 """
363 self._chromeos_interface.log('Corrupting kernel %s' % section)
364 self._kernel_handler.corrupt_kernel(section)
365
366
367 @allow_multiple_section_input
368 def restore_kernel(self, section):
369 """Restore the requested kernel section (previously corrupted).
370
371 Args:
372 section: A kernel section, either 'a' or 'b'.
373 """
374 self._chromeos_interface.log('restoring kernel %s' % section)
375 self._kernel_handler.restore_kernel(section)
376
377
Tom Wai-Hong Tam07278c22012-02-08 16:53:00 +0800378 def _modify_kernel_version(self, section, delta):
379 """Modify kernel version for the requested section, by adding delta.
380
381 The passed in delta, a positive or a negative number, is added to the
382 original kernel version.
383 """
384 original_version = self._kernel_handler.get_version(section)
385 new_version = original_version + delta
386 self._chromeos_interface.log(
387 'Setting kernel section %s version from %d to %d' % (
388 section, original_version, new_version))
389 self._kernel_handler.set_version(section, new_version)
390
391
392 @allow_multiple_section_input
393 def move_kernel_backward(self, section):
394 """Decrement kernel version for the requested section."""
395 self._modify_kernel_version(section, -1)
396
397
398 @allow_multiple_section_input
399 def move_kernel_forward(self, section):
400 """Increase kernel version for the requested section."""
401 self._modify_kernel_version(section, 1)
402
403
Tom Wai-Hong Tam48958832011-12-30 10:16:57 +0800404 def run_cgpt_test_loop(self):
405 """Run the CgptState test loop. The tst logic is handled in the client.
406
407 Returns:
408 0: there are more cgpt tests to execute.
409 1: no more CgptState test, finished.
410 """
411 return self._cgpt_state.test_loop()
412
413
414 def set_cgpt_test_step(self, step):
415 """Set the CgptState test step.
416
417 Args:
418 step: A test step number.
419 """
420 self._cgpt_state.set_step(step)
421
422
423 def get_cgpt_test_step(self):
424 """Get the CgptState test step.
425
426 Returns:
427 A test step number.
428 """
429 return self._cgpt_state.get_step()
430
431
Tom Wai-Hong Tambea57b32011-09-02 18:27:47 +0800432 def cleanup(self):
433 """Cleanup for the RPC server. Currently nothing."""
434 pass
435
436
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700437def main():
438 parser = OptionParser(usage='Usage: %prog [options]')
439 parser.add_option('--port', type='int', dest='port', default=9990,
440 help='port number of XMLRPC server')
441 (options, args) = parser.parse_args()
442
443 faft_client = FAFTClient()
444
445 # Launch the XMLRPC server to provide FAFTClient commands.
Tom Wai-Hong Tam4a257e52011-11-12 08:36:22 +0800446 server = SimpleXMLRPCServer(('localhost', options.port), allow_none=True,
447 logRequests=False)
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700448 server.register_introspection_functions()
449 server.register_instance(faft_client)
450 print 'XMLRPC Server: Serving FAFTClient on port %s' % options.port
451 server.serve_forever()
452
453
454if __name__ == '__main__':
455 main()