blob: f147a214711a2f06fce2fe728a8fe80923b07fb0 [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 Tam23870e02012-08-24 16:15:34 +080066 _ec_image: An object to automate EC image for autest.
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -070067 _kernel_handler: An object to provide kernel related actions.
68 _tpm_handler: An object to control TPM device.
ctchangc7e55ea2012-08-09 16:19:14 +080069 _temp_path: Path of a temp directory.
70 _keys_path: Path of a directory, keys/, in temp directory.
71 _work_path: Path of a directory, work/, in temp directory.
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -070072 """
73
74 def __init__(self):
75 """Initialize the data attributes of this class."""
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -070076 # TODO(waihong): Move the explicit object.init() methods to the
77 # objects' constructors (ChromeOSInterface, FlashromHandler,
78 # KernelHandler, and TpmHandler).
79 self._chromeos_interface = chromeos_interface.ChromeOSInterface(False)
Tom Wai-Hong Tam48958832011-12-30 10:16:57 +080080 # We keep the state of FAFT test in a permanent directory over reboots.
Tom Wai-Hong Tam07278c22012-02-08 16:53:00 +080081 state_dir = '/var/tmp/faft'
82 self._chromeos_interface.init(state_dir, log_file='/tmp/faft_log.txt')
83 os.chdir(state_dir)
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -070084
Vic Yang13d22ec2012-06-18 15:12:47 +080085 self._bios_handler = LazyFlashromHandlerProxy(
86 saft_flashrom_util,
Vic Yang59cac9c2012-05-21 15:28:42 +080087 self._chromeos_interface,
88 None,
89 '/usr/share/vboot/devkeys',
90 'bios')
Vic Yang59cac9c2012-05-21 15:28:42 +080091
Todd Brochf2b1d012012-06-14 12:55:21 -070092 self._ec_handler = None
93 if not os.system("mosys ec info"):
Vic Yang13d22ec2012-06-18 15:12:47 +080094 self._ec_handler = LazyFlashromHandlerProxy(
95 saft_flashrom_util,
Todd Brochf2b1d012012-06-14 12:55:21 -070096 self._chromeos_interface,
Vic Yang13d22ec2012-06-18 15:12:47 +080097 'ec_root_key.vpubk',
Todd Brochf2b1d012012-06-14 12:55:21 -070098 '/usr/share/vboot/devkeys',
99 'ec')
Todd Brochf2b1d012012-06-14 12:55:21 -0700100
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700101
102 self._kernel_handler = kernel_handler.KernelHandler()
Tom Wai-Hong Tam07278c22012-02-08 16:53:00 +0800103 # TODO(waihong): The dev_key_path is a new argument. We do that in
104 # order not to break the old image and still be able to run.
105 try:
106 self._kernel_handler.init(self._chromeos_interface,
107 dev_key_path='/usr/share/vboot/devkeys')
108 except:
109 # Copy the key to the current working directory.
110 shutil.copy('/usr/share/vboot/devkeys/kernel_data_key.vbprivk', '.')
111 self._kernel_handler.init(self._chromeos_interface)
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700112
113 self._tpm_handler = tpm_handler.TpmHandler()
114 self._tpm_handler.init(self._chromeos_interface)
115
Tom Wai-Hong Tam48958832011-12-30 10:16:57 +0800116 self._cgpt_state = cgpt_state.CgptState(
Tom Wai-Hong Tamed2231c2012-07-27 14:39:46 +0800117 'SHORT', self._chromeos_interface, self.get_root_dev())
Tom Wai-Hong Tam48958832011-12-30 10:16:57 +0800118
ctchangc7e55ea2012-08-09 16:19:14 +0800119 # Initialize temporary directory path
120 self._temp_path = '/var/tmp/faft/autest'
121 self._keys_path = os.path.join(self._temp_path, 'keys')
122 self._work_path = os.path.join(self._temp_path, 'work')
123
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700124
Tom Wai-Hong Tame8f291a2011-12-08 22:03:53 +0800125 def _dispatch(self, method, params):
126 """This _dispatch method handles string conversion especially.
127
128 Since we turn off allow_dotted_names option. So any string conversion,
129 like str(FAFTClient.method), i.e. FAFTClient.method.__str__, failed
130 via XML RPC call.
131 """
132 is_str = method.endswith('.__str__')
133 if is_str:
134 method = method.rsplit('.', 1)[0]
135 try:
136 func = getattr(self, method)
137 except AttributeError:
138 raise Exception('method "%s" is not supported' % method)
139 else:
140 if is_str:
141 return str(func)
142 else:
143 return func(*params)
144
145
Tom Wai-Hong Tambea57b32011-09-02 18:27:47 +0800146 def is_available(self):
147 """Function for polling the RPC server availability.
148
149 Returns:
150 Always True.
151 """
152 return True
153
154
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700155 def run_shell_command(self, command):
156 """Run shell command.
157
158 Args:
159 command: A shell command to be run.
160 """
161 self._chromeos_interface.log('Requesting run shell command')
162 self._chromeos_interface.run_shell_command(command)
163
164
165 def run_shell_command_get_output(self, command):
166 """Run shell command and get its console output.
167
168 Args:
169 command: A shell command to be run.
170
171 Returns:
172 A list of strings stripped of the newline characters.
173 """
174 self._chromeos_interface.log(
175 'Requesting run shell command and get its console output')
176 return self._chromeos_interface.run_shell_command_get_output(command)
177
178
179 def software_reboot(self):
180 """Request software reboot."""
181 self._chromeos_interface.log('Requesting software reboot')
182 self._chromeos_interface.run_shell_command('reboot')
183
184
Tom Wai-Hong Tam678ab152011-12-14 15:27:24 +0800185 def get_platform_name(self):
186 """Get the platform name of the current system.
187
188 Returns:
189 A string of the platform name.
190 """
191 self._chromeos_interface.log('Requesting get platform name')
192 return self._chromeos_interface.run_shell_command_get_output(
193 'mosys platform name')[0]
194
195
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700196 def get_crossystem_value(self, key):
197 """Get crossystem value of the requested key.
198
199 Args:
200 key: A crossystem key.
201
202 Returns:
203 A string of the requested crossystem value.
204 """
205 self._chromeos_interface.log('Requesting get crossystem value')
206 return self._chromeos_interface.run_shell_command_get_output(
207 'crossystem %s' % key)[0]
208
209
Tom Wai-Hong Tamcfda61f2011-11-02 17:41:01 +0800210 def get_root_dev(self):
211 """Get the name of root device without partition number.
212
213 Returns:
214 A string of the root device without partition number.
215 """
216 self._chromeos_interface.log('Requesting get root device')
217 return self._chromeos_interface.get_root_dev()
218
219
220 def get_root_part(self):
221 """Get the name of root device with partition number.
222
223 Returns:
224 A string of the root device with partition number.
225 """
226 self._chromeos_interface.log('Requesting get root part')
227 return self._chromeos_interface.get_root_part()
228
229
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700230 def set_try_fw_b(self):
231 """Set 'Try Frimware B' flag in crossystem."""
232 self._chromeos_interface.log('Requesting restart with firmware B')
233 self._chromeos_interface.cs.fwb_tries = 1
234
235
Tom Wai-Hong Tam76c75072011-10-25 18:00:12 +0800236 def request_recovery_boot(self):
237 """Request running in recovery mode on the restart."""
238 self._chromeos_interface.log('Requesting restart in recovery mode')
239 self._chromeos_interface.cs.request_recovery()
240
241
Tom Wai-Hong Tam8c9eed62011-12-28 15:05:05 +0800242 def get_gbb_flags(self):
243 """Get the GBB flags.
244
245 Returns:
246 An integer of the GBB flags.
247 """
248 self._chromeos_interface.log('Getting GBB flags')
Vic Yang59cac9c2012-05-21 15:28:42 +0800249 return self._bios_handler.get_gbb_flags()
Tom Wai-Hong Tam8c9eed62011-12-28 15:05:05 +0800250
251
Tom Wai-Hong Tam81f70002011-12-13 12:29:46 +0800252 def get_firmware_flags(self, section):
253 """Get the preamble flags of a firmware section.
254
255 Args:
256 section: A firmware section, either 'a' or 'b'.
257
258 Returns:
259 An integer of the preamble flags.
260 """
261 self._chromeos_interface.log('Getting preamble flags of firmware %s' %
262 section)
Vic Yang59cac9c2012-05-21 15:28:42 +0800263 return self._bios_handler.get_section_flags(section)
264
265
Vic Yang91b73cf2012-07-31 17:18:11 +0800266 def set_firmware_flags(self, section, flags):
267 """Set the preamble flags of a firmware section.
268
269 Args:
270 section: A firmware section, either 'a' or 'b'.
271 flags: An integer of preamble flags.
272 """
273 self._chromeos_interface.log(
274 'Setting preamble flags of firmware %s to %s' % (section, flags))
275 version = self.get_firmware_version(section)
276 self._bios_handler.set_section_version(section, version, flags,
277 write_through=True)
278
279
280 def get_EC_firmware_sha(self):
281 """Get SHA1 hash of EC RW firmware section. """
282 return self._ec_handler.get_section_sha('rw')
283
284
Tom Wai-Hong Tamc1c4deb2012-07-26 14:28:11 +0800285 def reload_firmware(self):
286 """Reload the firmware image that may be changed."""
287 self._bios_handler.reload()
288
289
Vic Yang59cac9c2012-05-21 15:28:42 +0800290 @allow_multiple_section_input
291 def corrupt_EC(self, section):
292 """Corrupt the requested EC section signature.
293
294 Args:
295 section: A EC section, either 'a' or 'b'.
296 """
297 self._chromeos_interface.log('Corrupting EC signature %s' %
298 section)
Vic Yang37a55462012-06-29 14:00:28 +0800299 self._ec_handler.corrupt_firmware(section, corrupt_all=True)
Vic Yang59cac9c2012-05-21 15:28:42 +0800300
301
302 @allow_multiple_section_input
303 def corrupt_EC_body(self, section):
304 """Corrupt the requested EC section body.
305
306 Args:
307 section: An EC section, either 'a' or 'b'.
308 """
309 self._chromeos_interface.log('Corrupting EC body %s' %
310 section)
Vic Yang37a55462012-06-29 14:00:28 +0800311 self._ec_handler.corrupt_firmware_body(section, corrupt_all=True)
Vic Yang59cac9c2012-05-21 15:28:42 +0800312
313
314 @allow_multiple_section_input
315 def restore_EC(self, section):
316 """Restore the previously corrupted EC section signature.
317
318 Args:
319 section: An EC section, either 'a' or 'b'.
320 """
321 self._chromeos_interface.log('Restoring EC signature %s' %
322 section)
Vic Yang37a55462012-06-29 14:00:28 +0800323 self._ec_handler.restore_firmware(section, restore_all=True)
Vic Yang59cac9c2012-05-21 15:28:42 +0800324
325
326 @allow_multiple_section_input
327 def restore_EC_body(self, section):
328 """Restore the previously corrupted EC section body.
329
330 Args:
331 section: An EC section, either 'a' or 'b'.
332 """
333 self._chromeos_interface.log('Restoring EC body %s' %
334 section)
Vic Yang37a55462012-06-29 14:00:28 +0800335 self._ec_handler.restore_firmware_body(section, restore_all=True)
Tom Wai-Hong Tam81f70002011-12-13 12:29:46 +0800336
337
Tom Wai-Hong Tam0e680af2011-10-26 14:32:55 +0800338 @allow_multiple_section_input
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700339 def corrupt_firmware(self, section):
Tom Wai-Hong Tam9aea8212011-12-12 15:08:45 +0800340 """Corrupt the requested firmware section signature.
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700341
342 Args:
343 section: A firmware section, either 'a' or 'b'.
344 """
Tom Wai-Hong Tam9aea8212011-12-12 15:08:45 +0800345 self._chromeos_interface.log('Corrupting firmware signature %s' %
346 section)
Vic Yang59cac9c2012-05-21 15:28:42 +0800347 self._bios_handler.corrupt_firmware(section)
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700348
349
Tom Wai-Hong Tam0e680af2011-10-26 14:32:55 +0800350 @allow_multiple_section_input
Tom Wai-Hong Tam81f70002011-12-13 12:29:46 +0800351 def corrupt_firmware_body(self, section):
352 """Corrupt the requested firmware section body.
353
354 Args:
355 section: A firmware section, either 'a' or 'b'.
356 """
357 self._chromeos_interface.log('Corrupting firmware body %s' %
358 section)
Vic Yang59cac9c2012-05-21 15:28:42 +0800359 self._bios_handler.corrupt_firmware_body(section)
Tom Wai-Hong Tam81f70002011-12-13 12:29:46 +0800360
361
362 @allow_multiple_section_input
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700363 def restore_firmware(self, section):
Tom Wai-Hong Tam9aea8212011-12-12 15:08:45 +0800364 """Restore the previously corrupted firmware section signature.
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700365
366 Args:
367 section: A firmware section, either 'a' or 'b'.
368 """
Tom Wai-Hong Tam9aea8212011-12-12 15:08:45 +0800369 self._chromeos_interface.log('Restoring firmware signature %s' %
370 section)
Vic Yang59cac9c2012-05-21 15:28:42 +0800371 self._bios_handler.restore_firmware(section)
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700372
373
Tom Wai-Hong Tamcfda61f2011-11-02 17:41:01 +0800374 @allow_multiple_section_input
Tom Wai-Hong Tam81f70002011-12-13 12:29:46 +0800375 def restore_firmware_body(self, section):
376 """Restore the previously corrupted firmware section body.
377
378 Args:
379 section: A firmware section, either 'a' or 'b'.
380 """
381 self._chromeos_interface.log('Restoring firmware body %s' %
382 section)
Vic Yang59cac9c2012-05-21 15:28:42 +0800383 self._bios_handler.restore_firmware_body(section)
Tom Wai-Hong Tam81f70002011-12-13 12:29:46 +0800384
385
Vic Yang91b73cf2012-07-31 17:18:11 +0800386 def get_firmware_version(self, section):
387 """Retrieve firmware version of a section."""
388 return self._bios_handler.get_section_version(section)
389
390
Tom Wai-Hong Tam46d03b12012-02-08 12:02:17 +0800391 def _modify_firmware_version(self, section, delta):
392 """Modify firmware version for the requested section, by adding delta.
393
394 The passed in delta, a positive or a negative number, is added to the
395 original firmware version.
396 """
Vic Yang91b73cf2012-07-31 17:18:11 +0800397 original_version = self.get_firmware_version(section)
Tom Wai-Hong Tam46d03b12012-02-08 12:02:17 +0800398 new_version = original_version + delta
Vic Yang59cac9c2012-05-21 15:28:42 +0800399 flags = self._bios_handler.get_section_flags(section)
Tom Wai-Hong Tam46d03b12012-02-08 12:02:17 +0800400 self._chromeos_interface.log(
401 'Setting firmware section %s version from %d to %d' % (
402 section, original_version, new_version))
Vic Yang59cac9c2012-05-21 15:28:42 +0800403 self._bios_handler.set_section_version(section, new_version, flags,
404 write_through=True)
Tom Wai-Hong Tam46d03b12012-02-08 12:02:17 +0800405
406 @allow_multiple_section_input
407 def move_firmware_backward(self, section):
408 """Decrement firmware version for the requested section."""
409 self._modify_firmware_version(section, -1)
410
411
412 @allow_multiple_section_input
413 def move_firmware_forward(self, section):
414 """Increase firmware version for the requested section."""
415 self._modify_firmware_version(section, 1)
416
ctchangc7e55ea2012-08-09 16:19:14 +0800417 def retrieve_firmware_version(self, section):
418 """Return firmware version."""
419 return self._bios_handler.get_section_version(section)
420
421 def retrieve_firmware_datakey_version(self, section):
422 """Return firmware data key version."""
423 return self._bios_handler.get_section_datakey_version(section)
424
425 def retrieve_kernel_subkey_version(self,section):
426 """Return kernel subkey version."""
427 return self._bios_handler.get_section_kernel_subkey_version(section)
Tom Wai-Hong Tam46d03b12012-02-08 12:02:17 +0800428
Tom Wai-Hong Tam81f70002011-12-13 12:29:46 +0800429 @allow_multiple_section_input
Tom Wai-Hong Tamcfda61f2011-11-02 17:41:01 +0800430 def corrupt_kernel(self, section):
431 """Corrupt the requested kernel section.
432
433 Args:
434 section: A kernel section, either 'a' or 'b'.
435 """
436 self._chromeos_interface.log('Corrupting kernel %s' % section)
437 self._kernel_handler.corrupt_kernel(section)
438
439
440 @allow_multiple_section_input
441 def restore_kernel(self, section):
442 """Restore the requested kernel section (previously corrupted).
443
444 Args:
445 section: A kernel section, either 'a' or 'b'.
446 """
447 self._chromeos_interface.log('restoring kernel %s' % section)
448 self._kernel_handler.restore_kernel(section)
449
450
Tom Wai-Hong Tam07278c22012-02-08 16:53:00 +0800451 def _modify_kernel_version(self, section, delta):
452 """Modify kernel version for the requested section, by adding delta.
453
454 The passed in delta, a positive or a negative number, is added to the
455 original kernel version.
456 """
457 original_version = self._kernel_handler.get_version(section)
458 new_version = original_version + delta
459 self._chromeos_interface.log(
460 'Setting kernel section %s version from %d to %d' % (
461 section, original_version, new_version))
462 self._kernel_handler.set_version(section, new_version)
463
464
465 @allow_multiple_section_input
466 def move_kernel_backward(self, section):
467 """Decrement kernel version for the requested section."""
468 self._modify_kernel_version(section, -1)
469
470
471 @allow_multiple_section_input
472 def move_kernel_forward(self, section):
473 """Increase kernel version for the requested section."""
474 self._modify_kernel_version(section, 1)
475
ctchangcc88d112012-08-23 17:56:15 +0800476
477 def retrieve_kernel_version(self, section):
478 """Return kernel version."""
479 return self._kernel_handler.get_version(section)
480
481
482 def retrieve_kernel_datakey_version(self, section):
483 """Return kernel datakey version."""
484 return self._kernel_handler.get_datakey_version(section)
485
486
Tom Wai-Hong Tam622d0ba2012-08-15 16:29:05 +0800487 def diff_kernel_a_b(self):
488 """Compare kernel A with B.
489
490 Returns:
491 True: if kernel A is different with B.
492 False: if kernel A is the same as B.
493 """
494 rootdev = self._chromeos_interface.get_root_dev()
495 kernel_a = self._chromeos_interface.join_part(rootdev, '3')
496 kernel_b = self._chromeos_interface.join_part(rootdev, '5')
497
498 # The signature (some kind of hash) for the kernel body is stored in
499 # the beginning. So compare the first 64KB (including header, preamble,
500 # and signature) should be enough to check them identical.
501 header_a = self._chromeos_interface.read_partition(kernel_a, 0x10000)
502 header_b = self._chromeos_interface.read_partition(kernel_b, 0x10000)
503
504 return header_a != header_b
Tom Wai-Hong Tam07278c22012-02-08 16:53:00 +0800505
Tom Wai-Hong Tam23870e02012-08-24 16:15:34 +0800506
507 def setup_EC_image(self, ec_path):
508 """Setup the new EC image for later update.
509
510 Args:
511 ec_path: The path of the EC image to be updated.
512 """
513 self._ec_image = flashrom_handler.FlashromHandler()
514 self._ec_image.init(saft_flashrom_util,
515 self._chromeos_interface,
516 'ec_root_key.vpubk',
517 '/usr/share/vboot/devkeys',
518 'ec')
519 self._ec_image.new_image(ec_path)
520
521
522 def get_EC_image_sha(self):
523 """Get SHA1 hash of RW firmware section of the EC autest image."""
524 return self._ec_image.get_section_sha('rw')
525
526
527 def update_EC_from_image(self, section, flags):
528 """Update EC via software sync design.
529
530 It copys the RW section from the EC image, which is loaded by calling
531 setup_EC_image(), to the EC area of the specified RW section on the
532 current AP firmware.
533
534 Args:
535 section: A firmware section on current BIOS, either 'a' or 'b'.
536 flags: An integer of preamble flags.
537 """
538 blob = self._ec_image.get_section_body('rw')
539 self._bios_handler.set_section_ecbin(section, blob,
540 write_through=True)
541 self.set_firmware_flags(section, flags)
542
543
Tom Wai-Hong Tamb63bc742012-08-30 20:41:30 +0800544 def dump_firmware(self, bios_path):
545 """Dump the current BIOS firmware to a file, specified by bios_path.
546
547 Args:
548 bios_path: The path of the BIOS image to be written.
549 """
550 self._bios_handler.dump_whole(bios_path)
551
552
553 def write_firmware(self, bios_path):
554 """Write the firmware from bios_path to the current system.
555
556 Args:
557 bios_path: The path of the source BIOS image.
558 """
559 self._bios_handler.new_image(bios_path)
560 self._bios_handler.write_whole()
561
562
Tom Wai-Hong Tam23870e02012-08-24 16:15:34 +0800563 def dump_EC_firmware(self, ec_path):
564 """Dump the current EC firmware to a file, specified by ec_path.
565
566 Args:
567 ec_path: The path of the EC image to be written.
568 """
569 self._ec_handler.dump_whole(ec_path)
570
571
Tom Wai-Hong Tam48958832011-12-30 10:16:57 +0800572 def run_cgpt_test_loop(self):
573 """Run the CgptState test loop. The tst logic is handled in the client.
574
575 Returns:
576 0: there are more cgpt tests to execute.
577 1: no more CgptState test, finished.
578 """
579 return self._cgpt_state.test_loop()
580
581
582 def set_cgpt_test_step(self, step):
583 """Set the CgptState test step.
584
585 Args:
586 step: A test step number.
587 """
588 self._cgpt_state.set_step(step)
589
590
591 def get_cgpt_test_step(self):
592 """Get the CgptState test step.
593
594 Returns:
595 A test step number.
596 """
597 return self._cgpt_state.get_step()
598
599
ctchangc7e55ea2012-08-09 16:19:14 +0800600 def setup_firmwareupdate_temp_dir(self):
601 """Setup temporary directory.
602
603 Devkeys are copied to _key_path. Then, shellball,
604 /usr/sbin/chromeos-firmwareupdate, is extracted to _work_path.
605 """
ctchang6b700df2012-08-20 13:48:07 +0800606
607 self.cleanup_firmwareupdate_temp_dir()
608
ctchangc7e55ea2012-08-09 16:19:14 +0800609 os.mkdir(self._temp_path)
610 os.chdir(self._temp_path)
611
612 os.mkdir(self._work_path)
613 shutil.copytree('/usr/share/vboot/devkeys/', self._keys_path)
614 self.run_shell_command(
615 'sh /usr/sbin/chromeos-firmwareupdate --sb_extract %s'
616 % self._work_path)
617
618
619 def retrieve_shellball_fwid(self):
620 """Retrieve shellball's fwid.
621
622 This method should be called after setup_firmwareupdate_temp_dir.
623
624 Returns:
625 Shellball's fwid.
626 """
627 self.run_shell_command('dump_fmap -x %s %s' %
628 (os.path.join(self._work_path, 'bios.bin'),
629 'RW_FWID_A'))
630
631 [fwid] = self.run_shell_command_get_output(
ctchangcc88d112012-08-23 17:56:15 +0800632 "cat RW_FWID_A | tr '\\0' '\\t' | cut -f1")
ctchangc7e55ea2012-08-09 16:19:14 +0800633
634 return fwid
635
636
637 def cleanup_firmwareupdate_temp_dir(self):
638 """Cleanup temporary directory."""
ctchang6b700df2012-08-20 13:48:07 +0800639 if os.path.isdir(self._temp_path):
640 shutil.rmtree(self._temp_path)
ctchangc7e55ea2012-08-09 16:19:14 +0800641
642
643 def repack_firmwareupdate_shellball(self, append):
644 """Repack shellball with new fwid.
645
646 New fwid follows the rule: [orignal_fwid]-[append].
647
648 Args:
649 append: use for new fwid naming.
650 """
651 shutil.copy('/usr/sbin/chromeos-firmwareupdate', '%s' %
652 os.path.join(self._temp_path,
653 'chromeos-firmwareupdate-%s' % append))
654
ctchang6b700df2012-08-20 13:48:07 +0800655 self.run_shell_command('sh %s --sb_repack %s' % (
656 os.path.join(self._temp_path,
657 'chromeos-firmwareupdate-%s' % append),
658 self._work_path))
ctchangc7e55ea2012-08-09 16:19:14 +0800659
660 args = ['-i']
661 args.append('"s/TARGET_FWID=\\"\\(.*\\)\\"/TARGET_FWID=\\"\\1.%s\\"/g"'
662 % append)
663 args.append('%s'
664 % os.path.join(self._temp_path,
665 'chromeos-firmwareupdate-%s' % append))
666 cmd = 'sed %s' % ' '.join(args)
667 self.run_shell_command(cmd)
668
669 args = ['-i']
670 args.append('"s/TARGET_UNSTABLE=\\".*\\"/TARGET_UNSTABLE=\\"\\"/g"')
671 args.append('%s'
672 % os.path.join(self._temp_path,
673 'chromeos-firmwareupdate-%s' % append))
674 cmd = 'sed %s' % ' '.join(args)
675 self.run_shell_command(cmd)
676
677
678 def resign_firmware(self, version):
679 """Resign firmware with version.
680
681 Args:
682 version: new firmware version number.
683 """
684 args = [os.path.join(self._work_path, 'bios.bin')]
685 args.append(os.path.join(self._temp_path, 'output.bin'))
686 args.append(os.path.join(self._keys_path, 'firmware_data_key.vbprivk'))
687 args.append(os.path.join(self._keys_path, 'firmware.keyblock'))
688 args.append(os.path.join(self._keys_path,
689 'dev_firmware_data_key.vbprivk'))
690 args.append(os.path.join(self._keys_path, 'dev_firmware.keyblock'))
691 args.append(os.path.join(self._keys_path, 'kernel_subkey.vbpubk'))
692 args.append('%d' % version)
693 args.append('1')
694 cmd = '/usr/share/vboot/bin/resign_firmwarefd.sh %s' % ' '.join(args)
695 self.run_shell_command(cmd)
696
697 shutil.copyfile('%s' % os.path.join(self._temp_path, 'output.bin'),
698 '%s' % os.path.join(self._work_path, 'bios.bin'))
699
700
701 def run_firmware_autoupdate(self, append):
702 """Do firmwareupdate with autoupdate mode using new shellball.
703
704 Args:
705 append: decide which shellball to use with format
706 chromeos-firmwareupdate-[append]
707 """
708 self.run_shell_command(
709 '/bin/sh %s --mode autoupdate --noupdate_ec'
710 % os.path.join(self._temp_path,
711 'chromeos-firmwareupdate-%s' % append))
712
713
714 def run_firmware_bootok(self, append):
715 """Do bootok mode using new shellball.
716
717 Copy firmware B to firmware A if reboot success.
718 """
719 self.run_shell_command(
720 '/bin/sh %s --mode bootok' % os.path.join(self._temp_path,
721 'chromeos-firmwareupdate-%s' % append))
722
723
724 def run_firmware_recovery(self):
725 """Recovery to original shellball."""
726 args = ['/usr/sbin/chromeos-firmwareupdate']
727 args.append('--mode recovery')
728 args.append('--noupdate_ec')
729 cmd = '/bin/sh %s' % ' '.join(args)
730 self.run_shell_command(cmd)
731
732
733 def get_temp_path(self):
734 """Get temporary directory path."""
735 return self._temp_path
736
737
ctchangcc88d112012-08-23 17:56:15 +0800738 def get_keys_path(self):
739 """Get keys path in temporary directory."""
740 return self._keys_path
741
742
743 def resign_kernel_with_keys(self, section, key_path=None):
744 """Resign kernel with temporary key."""
745 self._kernel_handler.resign_kernel(section, key_path)
746
747
Tom Wai-Hong Tambea57b32011-09-02 18:27:47 +0800748 def cleanup(self):
749 """Cleanup for the RPC server. Currently nothing."""
750 pass
751
752
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700753def main():
754 parser = OptionParser(usage='Usage: %prog [options]')
755 parser.add_option('--port', type='int', dest='port', default=9990,
756 help='port number of XMLRPC server')
757 (options, args) = parser.parse_args()
758
759 faft_client = FAFTClient()
760
761 # Launch the XMLRPC server to provide FAFTClient commands.
Tom Wai-Hong Tam4a257e52011-11-12 08:36:22 +0800762 server = SimpleXMLRPCServer(('localhost', options.port), allow_none=True,
763 logRequests=False)
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700764 server.register_introspection_functions()
765 server.register_instance(faft_client)
766 print 'XMLRPC Server: Serving FAFTClient on port %s' % options.port
767 server.serve_forever()
768
769
770if __name__ == '__main__':
771 main()