blob: d3c88a9923640977b782d4a369e820fd436fa84b [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
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
60 be accessed remotely.
61
62 Attributes:
63 _chromeos_interface: An object to encapsulate OS services functions.
Vic Yang59cac9c2012-05-21 15:28:42 +080064 _bios_handler: An object to automate BIOS flashrom testing.
65 _ec_handler: An object to automate EC flashrom testing.
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -070066 _kernel_handler: An object to provide kernel related actions.
67 _tpm_handler: An object to control TPM device.
ctchangc7e55ea2012-08-09 16:19:14 +080068 _temp_path: Path of a temp directory.
69 _keys_path: Path of a directory, keys/, in temp directory.
70 _work_path: Path of a directory, work/, in temp directory.
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -070071 """
72
73 def __init__(self):
74 """Initialize the data attributes of this class."""
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -070075 # TODO(waihong): Move the explicit object.init() methods to the
76 # objects' constructors (ChromeOSInterface, FlashromHandler,
77 # KernelHandler, and TpmHandler).
78 self._chromeos_interface = chromeos_interface.ChromeOSInterface(False)
Tom Wai-Hong Tam48958832011-12-30 10:16:57 +080079 # We keep the state of FAFT test in a permanent directory over reboots.
Tom Wai-Hong Tam07278c22012-02-08 16:53:00 +080080 state_dir = '/var/tmp/faft'
81 self._chromeos_interface.init(state_dir, log_file='/tmp/faft_log.txt')
82 os.chdir(state_dir)
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -070083
Vic Yang13d22ec2012-06-18 15:12:47 +080084 self._bios_handler = LazyFlashromHandlerProxy(
85 saft_flashrom_util,
Vic Yang59cac9c2012-05-21 15:28:42 +080086 self._chromeos_interface,
87 None,
88 '/usr/share/vboot/devkeys',
89 'bios')
Vic Yang59cac9c2012-05-21 15:28:42 +080090
Todd Brochf2b1d012012-06-14 12:55:21 -070091 self._ec_handler = None
92 if not os.system("mosys ec info"):
Vic Yang13d22ec2012-06-18 15:12:47 +080093 self._ec_handler = LazyFlashromHandlerProxy(
94 saft_flashrom_util,
Todd Brochf2b1d012012-06-14 12:55:21 -070095 self._chromeos_interface,
Vic Yang13d22ec2012-06-18 15:12:47 +080096 'ec_root_key.vpubk',
Todd Brochf2b1d012012-06-14 12:55:21 -070097 '/usr/share/vboot/devkeys',
98 'ec')
Todd Brochf2b1d012012-06-14 12:55:21 -070099
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700100
101 self._kernel_handler = kernel_handler.KernelHandler()
Tom Wai-Hong Tam07278c22012-02-08 16:53:00 +0800102 # TODO(waihong): The dev_key_path is a new argument. We do that in
103 # order not to break the old image and still be able to run.
104 try:
105 self._kernel_handler.init(self._chromeos_interface,
106 dev_key_path='/usr/share/vboot/devkeys')
107 except:
108 # Copy the key to the current working directory.
109 shutil.copy('/usr/share/vboot/devkeys/kernel_data_key.vbprivk', '.')
110 self._kernel_handler.init(self._chromeos_interface)
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700111
112 self._tpm_handler = tpm_handler.TpmHandler()
113 self._tpm_handler.init(self._chromeos_interface)
114
Tom Wai-Hong Tam48958832011-12-30 10:16:57 +0800115 self._cgpt_state = cgpt_state.CgptState(
Tom Wai-Hong Tamed2231c2012-07-27 14:39:46 +0800116 'SHORT', self._chromeos_interface, self.get_root_dev())
Tom Wai-Hong Tam48958832011-12-30 10:16:57 +0800117
ctchangc7e55ea2012-08-09 16:19:14 +0800118 # Initialize temporary directory path
119 self._temp_path = '/var/tmp/faft/autest'
120 self._keys_path = os.path.join(self._temp_path, 'keys')
121 self._work_path = os.path.join(self._temp_path, 'work')
122
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700123
Tom Wai-Hong Tame8f291a2011-12-08 22:03:53 +0800124 def _dispatch(self, method, params):
125 """This _dispatch method handles string conversion especially.
126
127 Since we turn off allow_dotted_names option. So any string conversion,
128 like str(FAFTClient.method), i.e. FAFTClient.method.__str__, failed
129 via XML RPC call.
130 """
131 is_str = method.endswith('.__str__')
132 if is_str:
133 method = method.rsplit('.', 1)[0]
134 try:
135 func = getattr(self, method)
136 except AttributeError:
137 raise Exception('method "%s" is not supported' % method)
138 else:
139 if is_str:
140 return str(func)
141 else:
142 return func(*params)
143
144
Tom Wai-Hong Tambea57b32011-09-02 18:27:47 +0800145 def is_available(self):
146 """Function for polling the RPC server availability.
147
148 Returns:
149 Always True.
150 """
151 return True
152
153
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700154 def run_shell_command(self, command):
155 """Run shell command.
156
157 Args:
158 command: A shell command to be run.
159 """
160 self._chromeos_interface.log('Requesting run shell command')
161 self._chromeos_interface.run_shell_command(command)
162
163
164 def run_shell_command_get_output(self, command):
165 """Run shell command and get its console output.
166
167 Args:
168 command: A shell command to be run.
169
170 Returns:
171 A list of strings stripped of the newline characters.
172 """
173 self._chromeos_interface.log(
174 'Requesting run shell command and get its console output')
175 return self._chromeos_interface.run_shell_command_get_output(command)
176
177
178 def software_reboot(self):
179 """Request software reboot."""
180 self._chromeos_interface.log('Requesting software reboot')
181 self._chromeos_interface.run_shell_command('reboot')
182
183
Tom Wai-Hong Tam678ab152011-12-14 15:27:24 +0800184 def get_platform_name(self):
185 """Get the platform name of the current system.
186
187 Returns:
188 A string of the platform name.
189 """
190 self._chromeos_interface.log('Requesting get platform name')
191 return self._chromeos_interface.run_shell_command_get_output(
192 'mosys platform name')[0]
193
194
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700195 def get_crossystem_value(self, key):
196 """Get crossystem value of the requested key.
197
198 Args:
199 key: A crossystem key.
200
201 Returns:
202 A string of the requested crossystem value.
203 """
204 self._chromeos_interface.log('Requesting get crossystem value')
205 return self._chromeos_interface.run_shell_command_get_output(
206 'crossystem %s' % key)[0]
207
208
Tom Wai-Hong Tamcfda61f2011-11-02 17:41:01 +0800209 def get_root_dev(self):
210 """Get the name of root device without partition number.
211
212 Returns:
213 A string of the root device without partition number.
214 """
215 self._chromeos_interface.log('Requesting get root device')
216 return self._chromeos_interface.get_root_dev()
217
218
219 def get_root_part(self):
220 """Get the name of root device with partition number.
221
222 Returns:
223 A string of the root device with partition number.
224 """
225 self._chromeos_interface.log('Requesting get root part')
226 return self._chromeos_interface.get_root_part()
227
228
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700229 def set_try_fw_b(self):
230 """Set 'Try Frimware B' flag in crossystem."""
231 self._chromeos_interface.log('Requesting restart with firmware B')
232 self._chromeos_interface.cs.fwb_tries = 1
233
234
Tom Wai-Hong Tam76c75072011-10-25 18:00:12 +0800235 def request_recovery_boot(self):
236 """Request running in recovery mode on the restart."""
237 self._chromeos_interface.log('Requesting restart in recovery mode')
238 self._chromeos_interface.cs.request_recovery()
239
240
Tom Wai-Hong Tam8c9eed62011-12-28 15:05:05 +0800241 def get_gbb_flags(self):
242 """Get the GBB flags.
243
244 Returns:
245 An integer of the GBB flags.
246 """
247 self._chromeos_interface.log('Getting GBB flags')
Vic Yang59cac9c2012-05-21 15:28:42 +0800248 return self._bios_handler.get_gbb_flags()
Tom Wai-Hong Tam8c9eed62011-12-28 15:05:05 +0800249
250
Tom Wai-Hong Tam81f70002011-12-13 12:29:46 +0800251 def get_firmware_flags(self, section):
252 """Get the preamble flags of a firmware section.
253
254 Args:
255 section: A firmware section, either 'a' or 'b'.
256
257 Returns:
258 An integer of the preamble flags.
259 """
260 self._chromeos_interface.log('Getting preamble flags of firmware %s' %
261 section)
Vic Yang59cac9c2012-05-21 15:28:42 +0800262 return self._bios_handler.get_section_flags(section)
263
264
Vic Yang91b73cf2012-07-31 17:18:11 +0800265 def set_firmware_flags(self, section, flags):
266 """Set the preamble flags of a firmware section.
267
268 Args:
269 section: A firmware section, either 'a' or 'b'.
270 flags: An integer of preamble flags.
271 """
272 self._chromeos_interface.log(
273 'Setting preamble flags of firmware %s to %s' % (section, flags))
274 version = self.get_firmware_version(section)
275 self._bios_handler.set_section_version(section, version, flags,
276 write_through=True)
277
278
279 def get_EC_firmware_sha(self):
280 """Get SHA1 hash of EC RW firmware section. """
281 return self._ec_handler.get_section_sha('rw')
282
283
Tom Wai-Hong Tamc1c4deb2012-07-26 14:28:11 +0800284 def reload_firmware(self):
285 """Reload the firmware image that may be changed."""
286 self._bios_handler.reload()
287
288
Vic Yang59cac9c2012-05-21 15:28:42 +0800289 @allow_multiple_section_input
290 def corrupt_EC(self, section):
291 """Corrupt the requested EC section signature.
292
293 Args:
294 section: A EC section, either 'a' or 'b'.
295 """
296 self._chromeos_interface.log('Corrupting EC signature %s' %
297 section)
Vic Yang37a55462012-06-29 14:00:28 +0800298 self._ec_handler.corrupt_firmware(section, corrupt_all=True)
Vic Yang59cac9c2012-05-21 15:28:42 +0800299
300
301 @allow_multiple_section_input
302 def corrupt_EC_body(self, section):
303 """Corrupt the requested EC section body.
304
305 Args:
306 section: An EC section, either 'a' or 'b'.
307 """
308 self._chromeos_interface.log('Corrupting EC body %s' %
309 section)
Vic Yang37a55462012-06-29 14:00:28 +0800310 self._ec_handler.corrupt_firmware_body(section, corrupt_all=True)
Vic Yang59cac9c2012-05-21 15:28:42 +0800311
312
313 @allow_multiple_section_input
314 def restore_EC(self, section):
315 """Restore the previously corrupted EC section signature.
316
317 Args:
318 section: An EC section, either 'a' or 'b'.
319 """
320 self._chromeos_interface.log('Restoring EC signature %s' %
321 section)
Vic Yang37a55462012-06-29 14:00:28 +0800322 self._ec_handler.restore_firmware(section, restore_all=True)
Vic Yang59cac9c2012-05-21 15:28:42 +0800323
324
325 @allow_multiple_section_input
326 def restore_EC_body(self, section):
327 """Restore the previously corrupted EC section body.
328
329 Args:
330 section: An EC section, either 'a' or 'b'.
331 """
332 self._chromeos_interface.log('Restoring EC body %s' %
333 section)
Vic Yang37a55462012-06-29 14:00:28 +0800334 self._ec_handler.restore_firmware_body(section, restore_all=True)
Tom Wai-Hong Tam81f70002011-12-13 12:29:46 +0800335
336
Tom Wai-Hong Tam0e680af2011-10-26 14:32:55 +0800337 @allow_multiple_section_input
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700338 def corrupt_firmware(self, section):
Tom Wai-Hong Tam9aea8212011-12-12 15:08:45 +0800339 """Corrupt the requested firmware section signature.
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700340
341 Args:
342 section: A firmware section, either 'a' or 'b'.
343 """
Tom Wai-Hong Tam9aea8212011-12-12 15:08:45 +0800344 self._chromeos_interface.log('Corrupting firmware signature %s' %
345 section)
Vic Yang59cac9c2012-05-21 15:28:42 +0800346 self._bios_handler.corrupt_firmware(section)
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700347
348
Tom Wai-Hong Tam0e680af2011-10-26 14:32:55 +0800349 @allow_multiple_section_input
Tom Wai-Hong Tam81f70002011-12-13 12:29:46 +0800350 def corrupt_firmware_body(self, section):
351 """Corrupt the requested firmware section body.
352
353 Args:
354 section: A firmware section, either 'a' or 'b'.
355 """
356 self._chromeos_interface.log('Corrupting firmware body %s' %
357 section)
Vic Yang59cac9c2012-05-21 15:28:42 +0800358 self._bios_handler.corrupt_firmware_body(section)
Tom Wai-Hong Tam81f70002011-12-13 12:29:46 +0800359
360
361 @allow_multiple_section_input
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700362 def restore_firmware(self, section):
Tom Wai-Hong Tam9aea8212011-12-12 15:08:45 +0800363 """Restore the previously corrupted firmware section signature.
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700364
365 Args:
366 section: A firmware section, either 'a' or 'b'.
367 """
Tom Wai-Hong Tam9aea8212011-12-12 15:08:45 +0800368 self._chromeos_interface.log('Restoring firmware signature %s' %
369 section)
Vic Yang59cac9c2012-05-21 15:28:42 +0800370 self._bios_handler.restore_firmware(section)
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700371
372
Tom Wai-Hong Tamcfda61f2011-11-02 17:41:01 +0800373 @allow_multiple_section_input
Tom Wai-Hong Tam81f70002011-12-13 12:29:46 +0800374 def restore_firmware_body(self, section):
375 """Restore the previously corrupted firmware section body.
376
377 Args:
378 section: A firmware section, either 'a' or 'b'.
379 """
380 self._chromeos_interface.log('Restoring firmware body %s' %
381 section)
Vic Yang59cac9c2012-05-21 15:28:42 +0800382 self._bios_handler.restore_firmware_body(section)
Tom Wai-Hong Tam81f70002011-12-13 12:29:46 +0800383
384
Vic Yang91b73cf2012-07-31 17:18:11 +0800385 def get_firmware_version(self, section):
386 """Retrieve firmware version of a section."""
387 return self._bios_handler.get_section_version(section)
388
389
Tom Wai-Hong Tam46d03b12012-02-08 12:02:17 +0800390 def _modify_firmware_version(self, section, delta):
391 """Modify firmware version for the requested section, by adding delta.
392
393 The passed in delta, a positive or a negative number, is added to the
394 original firmware version.
395 """
Vic Yang91b73cf2012-07-31 17:18:11 +0800396 original_version = self.get_firmware_version(section)
Tom Wai-Hong Tam46d03b12012-02-08 12:02:17 +0800397 new_version = original_version + delta
Vic Yang59cac9c2012-05-21 15:28:42 +0800398 flags = self._bios_handler.get_section_flags(section)
Tom Wai-Hong Tam46d03b12012-02-08 12:02:17 +0800399 self._chromeos_interface.log(
400 'Setting firmware section %s version from %d to %d' % (
401 section, original_version, new_version))
Vic Yang59cac9c2012-05-21 15:28:42 +0800402 self._bios_handler.set_section_version(section, new_version, flags,
403 write_through=True)
Tom Wai-Hong Tam46d03b12012-02-08 12:02:17 +0800404
405 @allow_multiple_section_input
406 def move_firmware_backward(self, section):
407 """Decrement firmware version for the requested section."""
408 self._modify_firmware_version(section, -1)
409
410
411 @allow_multiple_section_input
412 def move_firmware_forward(self, section):
413 """Increase firmware version for the requested section."""
414 self._modify_firmware_version(section, 1)
415
ctchangc7e55ea2012-08-09 16:19:14 +0800416 def retrieve_firmware_version(self, section):
417 """Return firmware version."""
418 return self._bios_handler.get_section_version(section)
419
420 def retrieve_firmware_datakey_version(self, section):
421 """Return firmware data key version."""
422 return self._bios_handler.get_section_datakey_version(section)
423
424 def retrieve_kernel_subkey_version(self,section):
425 """Return kernel subkey version."""
426 return self._bios_handler.get_section_kernel_subkey_version(section)
Tom Wai-Hong Tam46d03b12012-02-08 12:02:17 +0800427
Tom Wai-Hong Tam81f70002011-12-13 12:29:46 +0800428 @allow_multiple_section_input
Tom Wai-Hong Tamcfda61f2011-11-02 17:41:01 +0800429 def corrupt_kernel(self, section):
430 """Corrupt the requested kernel section.
431
432 Args:
433 section: A kernel section, either 'a' or 'b'.
434 """
435 self._chromeos_interface.log('Corrupting kernel %s' % section)
436 self._kernel_handler.corrupt_kernel(section)
437
438
439 @allow_multiple_section_input
440 def restore_kernel(self, section):
441 """Restore the requested kernel section (previously corrupted).
442
443 Args:
444 section: A kernel section, either 'a' or 'b'.
445 """
446 self._chromeos_interface.log('restoring kernel %s' % section)
447 self._kernel_handler.restore_kernel(section)
448
449
Tom Wai-Hong Tam07278c22012-02-08 16:53:00 +0800450 def _modify_kernel_version(self, section, delta):
451 """Modify kernel version for the requested section, by adding delta.
452
453 The passed in delta, a positive or a negative number, is added to the
454 original kernel version.
455 """
456 original_version = self._kernel_handler.get_version(section)
457 new_version = original_version + delta
458 self._chromeos_interface.log(
459 'Setting kernel section %s version from %d to %d' % (
460 section, original_version, new_version))
461 self._kernel_handler.set_version(section, new_version)
462
463
464 @allow_multiple_section_input
465 def move_kernel_backward(self, section):
466 """Decrement kernel version for the requested section."""
467 self._modify_kernel_version(section, -1)
468
469
470 @allow_multiple_section_input
471 def move_kernel_forward(self, section):
472 """Increase kernel version for the requested section."""
473 self._modify_kernel_version(section, 1)
474
ctchangcc88d112012-08-23 17:56:15 +0800475
476 def retrieve_kernel_version(self, section):
477 """Return kernel version."""
478 return self._kernel_handler.get_version(section)
479
480
481 def retrieve_kernel_datakey_version(self, section):
482 """Return kernel datakey version."""
483 return self._kernel_handler.get_datakey_version(section)
484
485
Tom Wai-Hong Tam622d0ba2012-08-15 16:29:05 +0800486 def diff_kernel_a_b(self):
487 """Compare kernel A with B.
488
489 Returns:
490 True: if kernel A is different with B.
491 False: if kernel A is the same as B.
492 """
493 rootdev = self._chromeos_interface.get_root_dev()
494 kernel_a = self._chromeos_interface.join_part(rootdev, '3')
495 kernel_b = self._chromeos_interface.join_part(rootdev, '5')
496
497 # The signature (some kind of hash) for the kernel body is stored in
498 # the beginning. So compare the first 64KB (including header, preamble,
499 # and signature) should be enough to check them identical.
500 header_a = self._chromeos_interface.read_partition(kernel_a, 0x10000)
501 header_b = self._chromeos_interface.read_partition(kernel_b, 0x10000)
502
503 return header_a != header_b
Tom Wai-Hong Tam07278c22012-02-08 16:53:00 +0800504
Tom Wai-Hong Tam48958832011-12-30 10:16:57 +0800505 def run_cgpt_test_loop(self):
506 """Run the CgptState test loop. The tst logic is handled in the client.
507
508 Returns:
509 0: there are more cgpt tests to execute.
510 1: no more CgptState test, finished.
511 """
512 return self._cgpt_state.test_loop()
513
514
515 def set_cgpt_test_step(self, step):
516 """Set the CgptState test step.
517
518 Args:
519 step: A test step number.
520 """
521 self._cgpt_state.set_step(step)
522
523
524 def get_cgpt_test_step(self):
525 """Get the CgptState test step.
526
527 Returns:
528 A test step number.
529 """
530 return self._cgpt_state.get_step()
531
532
ctchangc7e55ea2012-08-09 16:19:14 +0800533 def setup_firmwareupdate_temp_dir(self):
534 """Setup temporary directory.
535
536 Devkeys are copied to _key_path. Then, shellball,
537 /usr/sbin/chromeos-firmwareupdate, is extracted to _work_path.
538 """
ctchang6b700df2012-08-20 13:48:07 +0800539
540 self.cleanup_firmwareupdate_temp_dir()
541
ctchangc7e55ea2012-08-09 16:19:14 +0800542 os.mkdir(self._temp_path)
543 os.chdir(self._temp_path)
544
545 os.mkdir(self._work_path)
546 shutil.copytree('/usr/share/vboot/devkeys/', self._keys_path)
547 self.run_shell_command(
548 'sh /usr/sbin/chromeos-firmwareupdate --sb_extract %s'
549 % self._work_path)
550
551
552 def retrieve_shellball_fwid(self):
553 """Retrieve shellball's fwid.
554
555 This method should be called after setup_firmwareupdate_temp_dir.
556
557 Returns:
558 Shellball's fwid.
559 """
560 self.run_shell_command('dump_fmap -x %s %s' %
561 (os.path.join(self._work_path, 'bios.bin'),
562 'RW_FWID_A'))
563
564 [fwid] = self.run_shell_command_get_output(
ctchangcc88d112012-08-23 17:56:15 +0800565 "cat RW_FWID_A | tr '\\0' '\\t' | cut -f1")
ctchangc7e55ea2012-08-09 16:19:14 +0800566
567 return fwid
568
569
570 def cleanup_firmwareupdate_temp_dir(self):
571 """Cleanup temporary directory."""
ctchang6b700df2012-08-20 13:48:07 +0800572 if os.path.isdir(self._temp_path):
573 shutil.rmtree(self._temp_path)
ctchangc7e55ea2012-08-09 16:19:14 +0800574
575
576 def repack_firmwareupdate_shellball(self, append):
577 """Repack shellball with new fwid.
578
579 New fwid follows the rule: [orignal_fwid]-[append].
580
581 Args:
582 append: use for new fwid naming.
583 """
584 shutil.copy('/usr/sbin/chromeos-firmwareupdate', '%s' %
585 os.path.join(self._temp_path,
586 'chromeos-firmwareupdate-%s' % append))
587
ctchang6b700df2012-08-20 13:48:07 +0800588 self.run_shell_command('sh %s --sb_repack %s' % (
589 os.path.join(self._temp_path,
590 'chromeos-firmwareupdate-%s' % append),
591 self._work_path))
ctchangc7e55ea2012-08-09 16:19:14 +0800592
593 args = ['-i']
594 args.append('"s/TARGET_FWID=\\"\\(.*\\)\\"/TARGET_FWID=\\"\\1.%s\\"/g"'
595 % append)
596 args.append('%s'
597 % os.path.join(self._temp_path,
598 'chromeos-firmwareupdate-%s' % append))
599 cmd = 'sed %s' % ' '.join(args)
600 self.run_shell_command(cmd)
601
602 args = ['-i']
603 args.append('"s/TARGET_UNSTABLE=\\".*\\"/TARGET_UNSTABLE=\\"\\"/g"')
604 args.append('%s'
605 % os.path.join(self._temp_path,
606 'chromeos-firmwareupdate-%s' % append))
607 cmd = 'sed %s' % ' '.join(args)
608 self.run_shell_command(cmd)
609
610
611 def resign_firmware(self, version):
612 """Resign firmware with version.
613
614 Args:
615 version: new firmware version number.
616 """
617 args = [os.path.join(self._work_path, 'bios.bin')]
618 args.append(os.path.join(self._temp_path, 'output.bin'))
619 args.append(os.path.join(self._keys_path, 'firmware_data_key.vbprivk'))
620 args.append(os.path.join(self._keys_path, 'firmware.keyblock'))
621 args.append(os.path.join(self._keys_path,
622 'dev_firmware_data_key.vbprivk'))
623 args.append(os.path.join(self._keys_path, 'dev_firmware.keyblock'))
624 args.append(os.path.join(self._keys_path, 'kernel_subkey.vbpubk'))
625 args.append('%d' % version)
626 args.append('1')
627 cmd = '/usr/share/vboot/bin/resign_firmwarefd.sh %s' % ' '.join(args)
628 self.run_shell_command(cmd)
629
630 shutil.copyfile('%s' % os.path.join(self._temp_path, 'output.bin'),
631 '%s' % os.path.join(self._work_path, 'bios.bin'))
632
633
634 def run_firmware_autoupdate(self, append):
635 """Do firmwareupdate with autoupdate mode using new shellball.
636
637 Args:
638 append: decide which shellball to use with format
639 chromeos-firmwareupdate-[append]
640 """
641 self.run_shell_command(
642 '/bin/sh %s --mode autoupdate --noupdate_ec'
643 % os.path.join(self._temp_path,
644 'chromeos-firmwareupdate-%s' % append))
645
646
647 def run_firmware_bootok(self, append):
648 """Do bootok mode using new shellball.
649
650 Copy firmware B to firmware A if reboot success.
651 """
652 self.run_shell_command(
653 '/bin/sh %s --mode bootok' % os.path.join(self._temp_path,
654 'chromeos-firmwareupdate-%s' % append))
655
656
657 def run_firmware_recovery(self):
658 """Recovery to original shellball."""
659 args = ['/usr/sbin/chromeos-firmwareupdate']
660 args.append('--mode recovery')
661 args.append('--noupdate_ec')
662 cmd = '/bin/sh %s' % ' '.join(args)
663 self.run_shell_command(cmd)
664
665
666 def get_temp_path(self):
667 """Get temporary directory path."""
668 return self._temp_path
669
670
ctchangcc88d112012-08-23 17:56:15 +0800671 def get_keys_path(self):
672 """Get keys path in temporary directory."""
673 return self._keys_path
674
675
676 def resign_kernel_with_keys(self, section, key_path=None):
677 """Resign kernel with temporary key."""
678 self._kernel_handler.resign_kernel(section, key_path)
679
680
Tom Wai-Hong Tambea57b32011-09-02 18:27:47 +0800681 def cleanup(self):
682 """Cleanup for the RPC server. Currently nothing."""
683 pass
684
685
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700686def main():
687 parser = OptionParser(usage='Usage: %prog [options]')
688 parser.add_option('--port', type='int', dest='port', default=9990,
689 help='port number of XMLRPC server')
690 (options, args) = parser.parse_args()
691
692 faft_client = FAFTClient()
693
694 # Launch the XMLRPC server to provide FAFTClient commands.
Tom Wai-Hong Tam4a257e52011-11-12 08:36:22 +0800695 server = SimpleXMLRPCServer(('localhost', options.port), allow_none=True,
696 logRequests=False)
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700697 server.register_introspection_functions()
698 server.register_instance(faft_client)
699 print 'XMLRPC Server: Serving FAFTClient on port %s' % options.port
700 server.serve_forever()
701
702
703if __name__ == '__main__':
704 main()