blob: 5e97e889df3f42411eb98ba36051eff78c29290b [file] [log] [blame]
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -07001# Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
2# 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
Tom Wai-Hong Tam0e680af2011-10-26 14:32:55 +080012import functools
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -070013import sys
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -070014from optparse import OptionParser
15from SimpleXMLRPCServer import SimpleXMLRPCServer
16
17# Import libraries from SAFT.
Tom Wai-Hong Tamc1576b72011-11-08 11:36:16 +080018sys.path.append('/usr/local/sbin/firmware/saft')
Tom Wai-Hong Tam48958832011-12-30 10:16:57 +080019import cgpt_state
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -070020import chromeos_interface
21import flashrom_handler
22import kernel_handler
23import saft_flashrom_util
24import tpm_handler
25
26
Tom Wai-Hong Tam0e680af2011-10-26 14:32:55 +080027def allow_multiple_section_input(image_operator):
28 @functools.wraps(image_operator)
29 def wrapper(self, section):
30 if type(section) in (tuple, list):
31 for sec in section:
32 image_operator(self, sec)
33 else:
34 image_operator(self, section)
35 return wrapper
36
37
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -070038class FAFTClient(object):
39 """A class of FAFT client which aggregates some useful functions of SAFT.
40
41 This class can be exposed via a XMLRPC server such that its functions can
42 be accessed remotely.
43
44 Attributes:
45 _chromeos_interface: An object to encapsulate OS services functions.
46 _flashrom_handler: An object to automate flashrom testing.
47 _kernel_handler: An object to provide kernel related actions.
48 _tpm_handler: An object to control TPM device.
49 """
50
51 def __init__(self):
52 """Initialize the data attributes of this class."""
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -070053 # TODO(waihong): Move the explicit object.init() methods to the
54 # objects' constructors (ChromeOSInterface, FlashromHandler,
55 # KernelHandler, and TpmHandler).
56 self._chromeos_interface = chromeos_interface.ChromeOSInterface(False)
Tom Wai-Hong Tam48958832011-12-30 10:16:57 +080057 # We keep the state of FAFT test in a permanent directory over reboots.
58 self._chromeos_interface.init(state_dir='/var/tmp/faft',
59 log_file='/tmp/faft_log.txt')
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -070060
61 self._flashrom_handler = flashrom_handler.FlashromHandler()
62 self._flashrom_handler.init(saft_flashrom_util,
Tom Wai-Hong Tam46d03b12012-02-08 12:02:17 +080063 self._chromeos_interface,
64 None,
65 '/usr/share/vboot/devkeys')
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -070066 self._flashrom_handler.new_image()
67
68 self._kernel_handler = kernel_handler.KernelHandler()
69 self._kernel_handler.init(self._chromeos_interface)
70
71 self._tpm_handler = tpm_handler.TpmHandler()
72 self._tpm_handler.init(self._chromeos_interface)
73
Tom Wai-Hong Tam48958832011-12-30 10:16:57 +080074 self._cgpt_state = cgpt_state.CgptState(
75 'AUTO', self._chromeos_interface, self.get_root_dev())
76
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -070077
Tom Wai-Hong Tame8f291a2011-12-08 22:03:53 +080078 def _dispatch(self, method, params):
79 """This _dispatch method handles string conversion especially.
80
81 Since we turn off allow_dotted_names option. So any string conversion,
82 like str(FAFTClient.method), i.e. FAFTClient.method.__str__, failed
83 via XML RPC call.
84 """
85 is_str = method.endswith('.__str__')
86 if is_str:
87 method = method.rsplit('.', 1)[0]
88 try:
89 func = getattr(self, method)
90 except AttributeError:
91 raise Exception('method "%s" is not supported' % method)
92 else:
93 if is_str:
94 return str(func)
95 else:
96 return func(*params)
97
98
Tom Wai-Hong Tambea57b32011-09-02 18:27:47 +080099 def is_available(self):
100 """Function for polling the RPC server availability.
101
102 Returns:
103 Always True.
104 """
105 return True
106
107
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700108 def run_shell_command(self, command):
109 """Run shell command.
110
111 Args:
112 command: A shell command to be run.
113 """
114 self._chromeos_interface.log('Requesting run shell command')
115 self._chromeos_interface.run_shell_command(command)
116
117
118 def run_shell_command_get_output(self, command):
119 """Run shell command and get its console output.
120
121 Args:
122 command: A shell command to be run.
123
124 Returns:
125 A list of strings stripped of the newline characters.
126 """
127 self._chromeos_interface.log(
128 'Requesting run shell command and get its console output')
129 return self._chromeos_interface.run_shell_command_get_output(command)
130
131
132 def software_reboot(self):
133 """Request software reboot."""
134 self._chromeos_interface.log('Requesting software reboot')
135 self._chromeos_interface.run_shell_command('reboot')
136
137
Tom Wai-Hong Tam678ab152011-12-14 15:27:24 +0800138 def get_platform_name(self):
139 """Get the platform name of the current system.
140
141 Returns:
142 A string of the platform name.
143 """
144 self._chromeos_interface.log('Requesting get platform name')
145 return self._chromeos_interface.run_shell_command_get_output(
146 'mosys platform name')[0]
147
148
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700149 def get_crossystem_value(self, key):
150 """Get crossystem value of the requested key.
151
152 Args:
153 key: A crossystem key.
154
155 Returns:
156 A string of the requested crossystem value.
157 """
158 self._chromeos_interface.log('Requesting get crossystem value')
159 return self._chromeos_interface.run_shell_command_get_output(
160 'crossystem %s' % key)[0]
161
162
Tom Wai-Hong Tamcfda61f2011-11-02 17:41:01 +0800163 def get_root_dev(self):
164 """Get the name of root device without partition number.
165
166 Returns:
167 A string of the root device without partition number.
168 """
169 self._chromeos_interface.log('Requesting get root device')
170 return self._chromeos_interface.get_root_dev()
171
172
173 def get_root_part(self):
174 """Get the name of root device with partition number.
175
176 Returns:
177 A string of the root device with partition number.
178 """
179 self._chromeos_interface.log('Requesting get root part')
180 return self._chromeos_interface.get_root_part()
181
182
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700183 def set_try_fw_b(self):
184 """Set 'Try Frimware B' flag in crossystem."""
185 self._chromeos_interface.log('Requesting restart with firmware B')
186 self._chromeos_interface.cs.fwb_tries = 1
187
188
Tom Wai-Hong Tam76c75072011-10-25 18:00:12 +0800189 def request_recovery_boot(self):
190 """Request running in recovery mode on the restart."""
191 self._chromeos_interface.log('Requesting restart in recovery mode')
192 self._chromeos_interface.cs.request_recovery()
193
194
Tom Wai-Hong Tam8c9eed62011-12-28 15:05:05 +0800195 def get_gbb_flags(self):
196 """Get the GBB flags.
197
198 Returns:
199 An integer of the GBB flags.
200 """
201 self._chromeos_interface.log('Getting GBB flags')
202 return self._flashrom_handler.get_gbb_flags()
203
204
Tom Wai-Hong Tam81f70002011-12-13 12:29:46 +0800205 def get_firmware_flags(self, section):
206 """Get the preamble flags of a firmware section.
207
208 Args:
209 section: A firmware section, either 'a' or 'b'.
210
211 Returns:
212 An integer of the preamble flags.
213 """
214 self._chromeos_interface.log('Getting preamble flags of firmware %s' %
215 section)
216 return self._flashrom_handler.get_section_flags(section)
217
218
Tom Wai-Hong Tam0e680af2011-10-26 14:32:55 +0800219 @allow_multiple_section_input
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700220 def corrupt_firmware(self, section):
Tom Wai-Hong Tam9aea8212011-12-12 15:08:45 +0800221 """Corrupt the requested firmware section signature.
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700222
223 Args:
224 section: A firmware section, either 'a' or 'b'.
225 """
Tom Wai-Hong Tam9aea8212011-12-12 15:08:45 +0800226 self._chromeos_interface.log('Corrupting firmware signature %s' %
227 section)
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700228 self._flashrom_handler.corrupt_firmware(section)
229
230
Tom Wai-Hong Tam0e680af2011-10-26 14:32:55 +0800231 @allow_multiple_section_input
Tom Wai-Hong Tam81f70002011-12-13 12:29:46 +0800232 def corrupt_firmware_body(self, section):
233 """Corrupt the requested firmware section body.
234
235 Args:
236 section: A firmware section, either 'a' or 'b'.
237 """
238 self._chromeos_interface.log('Corrupting firmware body %s' %
239 section)
240 self._flashrom_handler.corrupt_firmware_body(section)
241
242
243 @allow_multiple_section_input
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700244 def restore_firmware(self, section):
Tom Wai-Hong Tam9aea8212011-12-12 15:08:45 +0800245 """Restore the previously corrupted firmware section signature.
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700246
247 Args:
248 section: A firmware section, either 'a' or 'b'.
249 """
Tom Wai-Hong Tam9aea8212011-12-12 15:08:45 +0800250 self._chromeos_interface.log('Restoring firmware signature %s' %
251 section)
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700252 self._flashrom_handler.restore_firmware(section)
253
254
Tom Wai-Hong Tamcfda61f2011-11-02 17:41:01 +0800255 @allow_multiple_section_input
Tom Wai-Hong Tam81f70002011-12-13 12:29:46 +0800256 def restore_firmware_body(self, section):
257 """Restore the previously corrupted firmware section body.
258
259 Args:
260 section: A firmware section, either 'a' or 'b'.
261 """
262 self._chromeos_interface.log('Restoring firmware body %s' %
263 section)
264 self._flashrom_handler.restore_firmware_body(section)
265
266
Tom Wai-Hong Tam46d03b12012-02-08 12:02:17 +0800267 def _modify_firmware_version(self, section, delta):
268 """Modify firmware version for the requested section, by adding delta.
269
270 The passed in delta, a positive or a negative number, is added to the
271 original firmware version.
272 """
273 original_version = self._flashrom_handler.get_section_version(section)
274 new_version = original_version + delta
275 flags = self._flashrom_handler.get_section_flags(section)
276 self._chromeos_interface.log(
277 'Setting firmware section %s version from %d to %d' % (
278 section, original_version, new_version))
279 self._flashrom_handler.set_section_version(section, new_version, flags,
280 write_through=True)
281
282 @allow_multiple_section_input
283 def move_firmware_backward(self, section):
284 """Decrement firmware version for the requested section."""
285 self._modify_firmware_version(section, -1)
286
287
288 @allow_multiple_section_input
289 def move_firmware_forward(self, section):
290 """Increase firmware version for the requested section."""
291 self._modify_firmware_version(section, 1)
292
293
Tom Wai-Hong Tam81f70002011-12-13 12:29:46 +0800294 @allow_multiple_section_input
Tom Wai-Hong Tamcfda61f2011-11-02 17:41:01 +0800295 def corrupt_kernel(self, section):
296 """Corrupt the requested kernel section.
297
298 Args:
299 section: A kernel section, either 'a' or 'b'.
300 """
301 self._chromeos_interface.log('Corrupting kernel %s' % section)
302 self._kernel_handler.corrupt_kernel(section)
303
304
305 @allow_multiple_section_input
306 def restore_kernel(self, section):
307 """Restore the requested kernel section (previously corrupted).
308
309 Args:
310 section: A kernel section, either 'a' or 'b'.
311 """
312 self._chromeos_interface.log('restoring kernel %s' % section)
313 self._kernel_handler.restore_kernel(section)
314
315
Tom Wai-Hong Tam48958832011-12-30 10:16:57 +0800316 def run_cgpt_test_loop(self):
317 """Run the CgptState test loop. The tst logic is handled in the client.
318
319 Returns:
320 0: there are more cgpt tests to execute.
321 1: no more CgptState test, finished.
322 """
323 return self._cgpt_state.test_loop()
324
325
326 def set_cgpt_test_step(self, step):
327 """Set the CgptState test step.
328
329 Args:
330 step: A test step number.
331 """
332 self._cgpt_state.set_step(step)
333
334
335 def get_cgpt_test_step(self):
336 """Get the CgptState test step.
337
338 Returns:
339 A test step number.
340 """
341 return self._cgpt_state.get_step()
342
343
Tom Wai-Hong Tambea57b32011-09-02 18:27:47 +0800344 def cleanup(self):
345 """Cleanup for the RPC server. Currently nothing."""
346 pass
347
348
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700349def main():
350 parser = OptionParser(usage='Usage: %prog [options]')
351 parser.add_option('--port', type='int', dest='port', default=9990,
352 help='port number of XMLRPC server')
353 (options, args) = parser.parse_args()
354
355 faft_client = FAFTClient()
356
357 # Launch the XMLRPC server to provide FAFTClient commands.
Tom Wai-Hong Tam4a257e52011-11-12 08:36:22 +0800358 server = SimpleXMLRPCServer(('localhost', options.port), allow_none=True,
359 logRequests=False)
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700360 server.register_introspection_functions()
361 server.register_instance(faft_client)
362 print 'XMLRPC Server: Serving FAFTClient on port %s' % options.port
363 server.serve_forever()
364
365
366if __name__ == '__main__':
367 main()