blob: f02fc3a3469a02779f3df4824bc1e141ad8b053b [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
Tom Wai-Hong Tamc0168912012-09-13 13:24:02 +080016from saft import cgpt_state, chromeos_interface, flashrom_handler
17from saft import kernel_handler, saft_flashrom_util, tpm_handler
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -070018
19
Tom Wai-Hong Tam0e680af2011-10-26 14:32:55 +080020def allow_multiple_section_input(image_operator):
21 @functools.wraps(image_operator)
22 def wrapper(self, section):
23 if type(section) in (tuple, list):
24 for sec in section:
25 image_operator(self, sec)
26 else:
27 image_operator(self, section)
28 return wrapper
29
30
Vic Yang13d22ec2012-06-18 15:12:47 +080031class LazyFlashromHandlerProxy:
32 _loaded = False
33 _obj = None
34
35 def __init__(self, *args, **kargs):
36 self._args = args
37 self._kargs = kargs
38
39 def _load(self):
40 self._obj = flashrom_handler.FlashromHandler()
41 self._obj.init(*self._args, **self._kargs)
42 self._obj.new_image()
43 self._loaded = True
44
45 def __getattr__(self, name):
46 if not self._loaded:
47 self._load()
48 return getattr(self._obj, name)
49
Tom Wai-Hong Tamc1c4deb2012-07-26 14:28:11 +080050 def reload(self):
51 self._loaded = False
52
Vic Yang13d22ec2012-06-18 15:12:47 +080053
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -070054class FAFTClient(object):
55 """A class of FAFT client which aggregates some useful functions of SAFT.
56
57 This class can be exposed via a XMLRPC server such that its functions can
58 be accessed remotely.
59
60 Attributes:
61 _chromeos_interface: An object to encapsulate OS services functions.
Vic Yang59cac9c2012-05-21 15:28:42 +080062 _bios_handler: An object to automate BIOS flashrom testing.
63 _ec_handler: An object to automate EC flashrom testing.
Tom Wai-Hong Tam23870e02012-08-24 16:15:34 +080064 _ec_image: An object to automate EC image for autest.
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -070065 _kernel_handler: An object to provide kernel related actions.
66 _tpm_handler: An object to control TPM device.
ctchangc7e55ea2012-08-09 16:19:14 +080067 _temp_path: Path of a temp directory.
68 _keys_path: Path of a directory, keys/, in temp directory.
69 _work_path: Path of a directory, work/, in temp directory.
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -070070 """
71
72 def __init__(self):
73 """Initialize the data attributes of this class."""
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -070074 # TODO(waihong): Move the explicit object.init() methods to the
75 # objects' constructors (ChromeOSInterface, FlashromHandler,
76 # KernelHandler, and TpmHandler).
77 self._chromeos_interface = chromeos_interface.ChromeOSInterface(False)
Tom Wai-Hong Tam48958832011-12-30 10:16:57 +080078 # We keep the state of FAFT test in a permanent directory over reboots.
Tom Wai-Hong Tam07278c22012-02-08 16:53:00 +080079 state_dir = '/var/tmp/faft'
80 self._chromeos_interface.init(state_dir, log_file='/tmp/faft_log.txt')
81 os.chdir(state_dir)
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -070082
Vic Yang13d22ec2012-06-18 15:12:47 +080083 self._bios_handler = LazyFlashromHandlerProxy(
84 saft_flashrom_util,
Vic Yang59cac9c2012-05-21 15:28:42 +080085 self._chromeos_interface,
86 None,
87 '/usr/share/vboot/devkeys',
88 'bios')
Vic Yang59cac9c2012-05-21 15:28:42 +080089
Todd Brochf2b1d012012-06-14 12:55:21 -070090 self._ec_handler = None
91 if not os.system("mosys ec info"):
Vic Yang13d22ec2012-06-18 15:12:47 +080092 self._ec_handler = LazyFlashromHandlerProxy(
93 saft_flashrom_util,
Todd Brochf2b1d012012-06-14 12:55:21 -070094 self._chromeos_interface,
Vic Yang13d22ec2012-06-18 15:12:47 +080095 'ec_root_key.vpubk',
Todd Brochf2b1d012012-06-14 12:55:21 -070096 '/usr/share/vboot/devkeys',
97 'ec')
Todd Brochf2b1d012012-06-14 12:55:21 -070098
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -070099
100 self._kernel_handler = kernel_handler.KernelHandler()
Tom Wai-Hong Tam07278c22012-02-08 16:53:00 +0800101 # TODO(waihong): The dev_key_path is a new argument. We do that in
102 # order not to break the old image and still be able to run.
103 try:
104 self._kernel_handler.init(self._chromeos_interface,
105 dev_key_path='/usr/share/vboot/devkeys')
106 except:
107 # Copy the key to the current working directory.
108 shutil.copy('/usr/share/vboot/devkeys/kernel_data_key.vbprivk', '.')
109 self._kernel_handler.init(self._chromeos_interface)
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700110
111 self._tpm_handler = tpm_handler.TpmHandler()
112 self._tpm_handler.init(self._chromeos_interface)
113
Tom Wai-Hong Tam48958832011-12-30 10:16:57 +0800114 self._cgpt_state = cgpt_state.CgptState(
Tom Wai-Hong Tamed2231c2012-07-27 14:39:46 +0800115 'SHORT', self._chromeos_interface, self.get_root_dev())
Tom Wai-Hong Tam48958832011-12-30 10:16:57 +0800116
ctchangc7e55ea2012-08-09 16:19:14 +0800117 # Initialize temporary directory path
118 self._temp_path = '/var/tmp/faft/autest'
119 self._keys_path = os.path.join(self._temp_path, 'keys')
120 self._work_path = os.path.join(self._temp_path, 'work')
121
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700122
Tom Wai-Hong Tame8f291a2011-12-08 22:03:53 +0800123 def _dispatch(self, method, params):
124 """This _dispatch method handles string conversion especially.
125
126 Since we turn off allow_dotted_names option. So any string conversion,
127 like str(FAFTClient.method), i.e. FAFTClient.method.__str__, failed
128 via XML RPC call.
129 """
130 is_str = method.endswith('.__str__')
131 if is_str:
132 method = method.rsplit('.', 1)[0]
133 try:
134 func = getattr(self, method)
135 except AttributeError:
136 raise Exception('method "%s" is not supported' % method)
137 else:
138 if is_str:
139 return str(func)
140 else:
141 return func(*params)
142
143
Tom Wai-Hong Tambea57b32011-09-02 18:27:47 +0800144 def is_available(self):
145 """Function for polling the RPC server availability.
146
147 Returns:
148 Always True.
149 """
150 return True
151
152
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700153 def run_shell_command(self, command):
154 """Run shell command.
155
156 Args:
157 command: A shell command to be run.
158 """
159 self._chromeos_interface.log('Requesting run shell command')
160 self._chromeos_interface.run_shell_command(command)
161
162
163 def run_shell_command_get_output(self, command):
164 """Run shell command and get its console output.
165
166 Args:
167 command: A shell command to be run.
168
169 Returns:
170 A list of strings stripped of the newline characters.
171 """
172 self._chromeos_interface.log(
173 'Requesting run shell command and get its console output')
174 return self._chromeos_interface.run_shell_command_get_output(command)
175
176
177 def software_reboot(self):
178 """Request software reboot."""
179 self._chromeos_interface.log('Requesting software reboot')
180 self._chromeos_interface.run_shell_command('reboot')
181
182
Tom Wai-Hong Tam678ab152011-12-14 15:27:24 +0800183 def get_platform_name(self):
184 """Get the platform name of the current system.
185
186 Returns:
187 A string of the platform name.
188 """
189 self._chromeos_interface.log('Requesting get platform name')
190 return self._chromeos_interface.run_shell_command_get_output(
191 'mosys platform name')[0]
192
193
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700194 def get_crossystem_value(self, key):
195 """Get crossystem value of the requested key.
196
197 Args:
198 key: A crossystem key.
199
200 Returns:
201 A string of the requested crossystem value.
202 """
203 self._chromeos_interface.log('Requesting get crossystem value')
204 return self._chromeos_interface.run_shell_command_get_output(
205 'crossystem %s' % key)[0]
206
207
Tom Wai-Hong Tamcfda61f2011-11-02 17:41:01 +0800208 def get_root_dev(self):
209 """Get the name of root device without partition number.
210
211 Returns:
212 A string of the root device without partition number.
213 """
214 self._chromeos_interface.log('Requesting get root device')
215 return self._chromeos_interface.get_root_dev()
216
217
218 def get_root_part(self):
219 """Get the name of root device with partition number.
220
221 Returns:
222 A string of the root device with partition number.
223 """
224 self._chromeos_interface.log('Requesting get root part')
225 return self._chromeos_interface.get_root_part()
226
227
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700228 def set_try_fw_b(self):
229 """Set 'Try Frimware B' flag in crossystem."""
230 self._chromeos_interface.log('Requesting restart with firmware B')
231 self._chromeos_interface.cs.fwb_tries = 1
232
233
Tom Wai-Hong Tam76c75072011-10-25 18:00:12 +0800234 def request_recovery_boot(self):
235 """Request running in recovery mode on the restart."""
236 self._chromeos_interface.log('Requesting restart in recovery mode')
237 self._chromeos_interface.cs.request_recovery()
238
239
Tom Wai-Hong Tam8c9eed62011-12-28 15:05:05 +0800240 def get_gbb_flags(self):
241 """Get the GBB flags.
242
243 Returns:
244 An integer of the GBB flags.
245 """
246 self._chromeos_interface.log('Getting GBB flags')
Vic Yang59cac9c2012-05-21 15:28:42 +0800247 return self._bios_handler.get_gbb_flags()
Tom Wai-Hong Tam8c9eed62011-12-28 15:05:05 +0800248
249
Tom Wai-Hong Tam81f70002011-12-13 12:29:46 +0800250 def get_firmware_flags(self, section):
251 """Get the preamble flags of a firmware section.
252
253 Args:
254 section: A firmware section, either 'a' or 'b'.
255
256 Returns:
257 An integer of the preamble flags.
258 """
259 self._chromeos_interface.log('Getting preamble flags of firmware %s' %
260 section)
Vic Yang59cac9c2012-05-21 15:28:42 +0800261 return self._bios_handler.get_section_flags(section)
262
263
Vic Yang91b73cf2012-07-31 17:18:11 +0800264 def set_firmware_flags(self, section, flags):
265 """Set the preamble flags of a firmware section.
266
267 Args:
268 section: A firmware section, either 'a' or 'b'.
269 flags: An integer of preamble flags.
270 """
271 self._chromeos_interface.log(
272 'Setting preamble flags of firmware %s to %s' % (section, flags))
273 version = self.get_firmware_version(section)
274 self._bios_handler.set_section_version(section, version, flags,
275 write_through=True)
276
277
Tom Wai-Hong Tam4e10b9f2012-09-06 16:23:02 +0800278 def get_firmware_sha(self, section):
279 """Get SHA1 hash of BIOS RW firmware section.
280
281 Args:
282 section: A firmware section, either 'a' or 'b'.
283 flags: An integer of preamble flags.
284 """
285 return self._bios_handler.get_section_sha(section)
286
287
Vic Yang91b73cf2012-07-31 17:18:11 +0800288 def get_EC_firmware_sha(self):
Tom Wai-Hong Tam4e10b9f2012-09-06 16:23:02 +0800289 """Get SHA1 hash of EC RW firmware section."""
Vic Yang91b73cf2012-07-31 17:18:11 +0800290 return self._ec_handler.get_section_sha('rw')
291
292
Tom Wai-Hong Tamc1c4deb2012-07-26 14:28:11 +0800293 def reload_firmware(self):
294 """Reload the firmware image that may be changed."""
295 self._bios_handler.reload()
296
297
Vic Yang59cac9c2012-05-21 15:28:42 +0800298 @allow_multiple_section_input
299 def corrupt_EC(self, section):
300 """Corrupt the requested EC section signature.
301
302 Args:
303 section: A EC section, either 'a' or 'b'.
304 """
305 self._chromeos_interface.log('Corrupting EC signature %s' %
306 section)
Vic Yang37a55462012-06-29 14:00:28 +0800307 self._ec_handler.corrupt_firmware(section, corrupt_all=True)
Vic Yang59cac9c2012-05-21 15:28:42 +0800308
309
310 @allow_multiple_section_input
311 def corrupt_EC_body(self, section):
312 """Corrupt the requested EC section body.
313
314 Args:
315 section: An EC section, either 'a' or 'b'.
316 """
317 self._chromeos_interface.log('Corrupting EC body %s' %
318 section)
Vic Yang37a55462012-06-29 14:00:28 +0800319 self._ec_handler.corrupt_firmware_body(section, corrupt_all=True)
Vic Yang59cac9c2012-05-21 15:28:42 +0800320
321
322 @allow_multiple_section_input
323 def restore_EC(self, section):
324 """Restore the previously corrupted EC section signature.
325
326 Args:
327 section: An EC section, either 'a' or 'b'.
328 """
329 self._chromeos_interface.log('Restoring EC signature %s' %
330 section)
Vic Yang37a55462012-06-29 14:00:28 +0800331 self._ec_handler.restore_firmware(section, restore_all=True)
Vic Yang59cac9c2012-05-21 15:28:42 +0800332
333
334 @allow_multiple_section_input
335 def restore_EC_body(self, section):
336 """Restore the previously corrupted EC section body.
337
338 Args:
339 section: An EC section, either 'a' or 'b'.
340 """
341 self._chromeos_interface.log('Restoring EC body %s' %
342 section)
Vic Yang37a55462012-06-29 14:00:28 +0800343 self._ec_handler.restore_firmware_body(section, restore_all=True)
Tom Wai-Hong Tam81f70002011-12-13 12:29:46 +0800344
345
Tom Wai-Hong Tam0e680af2011-10-26 14:32:55 +0800346 @allow_multiple_section_input
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700347 def corrupt_firmware(self, section):
Tom Wai-Hong Tam9aea8212011-12-12 15:08:45 +0800348 """Corrupt the requested firmware section signature.
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700349
350 Args:
351 section: A firmware section, either 'a' or 'b'.
352 """
Tom Wai-Hong Tam9aea8212011-12-12 15:08:45 +0800353 self._chromeos_interface.log('Corrupting firmware signature %s' %
354 section)
Vic Yang59cac9c2012-05-21 15:28:42 +0800355 self._bios_handler.corrupt_firmware(section)
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700356
357
Tom Wai-Hong Tam0e680af2011-10-26 14:32:55 +0800358 @allow_multiple_section_input
Tom Wai-Hong Tam81f70002011-12-13 12:29:46 +0800359 def corrupt_firmware_body(self, section):
360 """Corrupt the requested firmware section body.
361
362 Args:
363 section: A firmware section, either 'a' or 'b'.
364 """
365 self._chromeos_interface.log('Corrupting firmware body %s' %
366 section)
Vic Yang59cac9c2012-05-21 15:28:42 +0800367 self._bios_handler.corrupt_firmware_body(section)
Tom Wai-Hong Tam81f70002011-12-13 12:29:46 +0800368
369
370 @allow_multiple_section_input
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700371 def restore_firmware(self, section):
Tom Wai-Hong Tam9aea8212011-12-12 15:08:45 +0800372 """Restore the previously corrupted firmware section signature.
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700373
374 Args:
375 section: A firmware section, either 'a' or 'b'.
376 """
Tom Wai-Hong Tam9aea8212011-12-12 15:08:45 +0800377 self._chromeos_interface.log('Restoring firmware signature %s' %
378 section)
Vic Yang59cac9c2012-05-21 15:28:42 +0800379 self._bios_handler.restore_firmware(section)
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700380
381
Tom Wai-Hong Tamcfda61f2011-11-02 17:41:01 +0800382 @allow_multiple_section_input
Tom Wai-Hong Tam81f70002011-12-13 12:29:46 +0800383 def restore_firmware_body(self, section):
384 """Restore the previously corrupted firmware section body.
385
386 Args:
387 section: A firmware section, either 'a' or 'b'.
388 """
389 self._chromeos_interface.log('Restoring firmware body %s' %
390 section)
Vic Yang59cac9c2012-05-21 15:28:42 +0800391 self._bios_handler.restore_firmware_body(section)
Tom Wai-Hong Tam81f70002011-12-13 12:29:46 +0800392
393
Vic Yang91b73cf2012-07-31 17:18:11 +0800394 def get_firmware_version(self, section):
395 """Retrieve firmware version of a section."""
396 return self._bios_handler.get_section_version(section)
397
398
Tom Wai-Hong Tam46d03b12012-02-08 12:02:17 +0800399 def _modify_firmware_version(self, section, delta):
400 """Modify firmware version for the requested section, by adding delta.
401
402 The passed in delta, a positive or a negative number, is added to the
403 original firmware version.
404 """
Vic Yang91b73cf2012-07-31 17:18:11 +0800405 original_version = self.get_firmware_version(section)
Tom Wai-Hong Tam46d03b12012-02-08 12:02:17 +0800406 new_version = original_version + delta
Vic Yang59cac9c2012-05-21 15:28:42 +0800407 flags = self._bios_handler.get_section_flags(section)
Tom Wai-Hong Tam46d03b12012-02-08 12:02:17 +0800408 self._chromeos_interface.log(
409 'Setting firmware section %s version from %d to %d' % (
410 section, original_version, new_version))
Vic Yang59cac9c2012-05-21 15:28:42 +0800411 self._bios_handler.set_section_version(section, new_version, flags,
412 write_through=True)
Tom Wai-Hong Tam46d03b12012-02-08 12:02:17 +0800413
414 @allow_multiple_section_input
415 def move_firmware_backward(self, section):
416 """Decrement firmware version for the requested section."""
417 self._modify_firmware_version(section, -1)
418
419
420 @allow_multiple_section_input
421 def move_firmware_forward(self, section):
422 """Increase firmware version for the requested section."""
423 self._modify_firmware_version(section, 1)
424
ctchangc7e55ea2012-08-09 16:19:14 +0800425 def retrieve_firmware_version(self, section):
426 """Return firmware version."""
427 return self._bios_handler.get_section_version(section)
428
429 def retrieve_firmware_datakey_version(self, section):
430 """Return firmware data key version."""
431 return self._bios_handler.get_section_datakey_version(section)
432
433 def retrieve_kernel_subkey_version(self,section):
434 """Return kernel subkey version."""
435 return self._bios_handler.get_section_kernel_subkey_version(section)
Tom Wai-Hong Tam46d03b12012-02-08 12:02:17 +0800436
Tom Wai-Hong Tam81f70002011-12-13 12:29:46 +0800437 @allow_multiple_section_input
Tom Wai-Hong Tamcfda61f2011-11-02 17:41:01 +0800438 def corrupt_kernel(self, section):
439 """Corrupt the requested kernel section.
440
441 Args:
442 section: A kernel section, either 'a' or 'b'.
443 """
444 self._chromeos_interface.log('Corrupting kernel %s' % section)
445 self._kernel_handler.corrupt_kernel(section)
446
447
448 @allow_multiple_section_input
449 def restore_kernel(self, section):
450 """Restore the requested kernel section (previously corrupted).
451
452 Args:
453 section: A kernel section, either 'a' or 'b'.
454 """
455 self._chromeos_interface.log('restoring kernel %s' % section)
456 self._kernel_handler.restore_kernel(section)
457
458
Tom Wai-Hong Tam07278c22012-02-08 16:53:00 +0800459 def _modify_kernel_version(self, section, delta):
460 """Modify kernel version for the requested section, by adding delta.
461
462 The passed in delta, a positive or a negative number, is added to the
463 original kernel version.
464 """
465 original_version = self._kernel_handler.get_version(section)
466 new_version = original_version + delta
467 self._chromeos_interface.log(
468 'Setting kernel section %s version from %d to %d' % (
469 section, original_version, new_version))
470 self._kernel_handler.set_version(section, new_version)
471
472
473 @allow_multiple_section_input
474 def move_kernel_backward(self, section):
475 """Decrement kernel version for the requested section."""
476 self._modify_kernel_version(section, -1)
477
478
479 @allow_multiple_section_input
480 def move_kernel_forward(self, section):
481 """Increase kernel version for the requested section."""
482 self._modify_kernel_version(section, 1)
483
ctchangcc88d112012-08-23 17:56:15 +0800484
485 def retrieve_kernel_version(self, section):
486 """Return kernel version."""
487 return self._kernel_handler.get_version(section)
488
489
490 def retrieve_kernel_datakey_version(self, section):
491 """Return kernel datakey version."""
492 return self._kernel_handler.get_datakey_version(section)
493
494
Tom Wai-Hong Tam622d0ba2012-08-15 16:29:05 +0800495 def diff_kernel_a_b(self):
496 """Compare kernel A with B.
497
498 Returns:
499 True: if kernel A is different with B.
500 False: if kernel A is the same as B.
501 """
502 rootdev = self._chromeos_interface.get_root_dev()
503 kernel_a = self._chromeos_interface.join_part(rootdev, '3')
504 kernel_b = self._chromeos_interface.join_part(rootdev, '5')
505
506 # The signature (some kind of hash) for the kernel body is stored in
507 # the beginning. So compare the first 64KB (including header, preamble,
508 # and signature) should be enough to check them identical.
509 header_a = self._chromeos_interface.read_partition(kernel_a, 0x10000)
510 header_b = self._chromeos_interface.read_partition(kernel_b, 0x10000)
511
512 return header_a != header_b
Tom Wai-Hong Tam07278c22012-02-08 16:53:00 +0800513
Tom Wai-Hong Tam23870e02012-08-24 16:15:34 +0800514
515 def setup_EC_image(self, ec_path):
516 """Setup the new EC image for later update.
517
518 Args:
519 ec_path: The path of the EC image to be updated.
520 """
521 self._ec_image = flashrom_handler.FlashromHandler()
522 self._ec_image.init(saft_flashrom_util,
523 self._chromeos_interface,
524 'ec_root_key.vpubk',
525 '/usr/share/vboot/devkeys',
526 'ec')
527 self._ec_image.new_image(ec_path)
528
529
530 def get_EC_image_sha(self):
531 """Get SHA1 hash of RW firmware section of the EC autest image."""
532 return self._ec_image.get_section_sha('rw')
533
534
535 def update_EC_from_image(self, section, flags):
536 """Update EC via software sync design.
537
538 It copys the RW section from the EC image, which is loaded by calling
539 setup_EC_image(), to the EC area of the specified RW section on the
540 current AP firmware.
541
542 Args:
543 section: A firmware section on current BIOS, either 'a' or 'b'.
544 flags: An integer of preamble flags.
545 """
546 blob = self._ec_image.get_section_body('rw')
547 self._bios_handler.set_section_ecbin(section, blob,
548 write_through=True)
549 self.set_firmware_flags(section, flags)
550
551
Tom Wai-Hong Tamb63bc742012-08-30 20:41:30 +0800552 def dump_firmware(self, bios_path):
553 """Dump the current BIOS firmware to a file, specified by bios_path.
554
555 Args:
556 bios_path: The path of the BIOS image to be written.
557 """
558 self._bios_handler.dump_whole(bios_path)
559
560
561 def write_firmware(self, bios_path):
562 """Write the firmware from bios_path to the current system.
563
564 Args:
565 bios_path: The path of the source BIOS image.
566 """
567 self._bios_handler.new_image(bios_path)
568 self._bios_handler.write_whole()
569
570
Tom Wai-Hong Tam23870e02012-08-24 16:15:34 +0800571 def dump_EC_firmware(self, ec_path):
572 """Dump the current EC firmware to a file, specified by ec_path.
573
574 Args:
575 ec_path: The path of the EC image to be written.
576 """
577 self._ec_handler.dump_whole(ec_path)
578
579
Tom Wai-Hong Tam48958832011-12-30 10:16:57 +0800580 def run_cgpt_test_loop(self):
581 """Run the CgptState test loop. The tst logic is handled in the client.
582
583 Returns:
584 0: there are more cgpt tests to execute.
585 1: no more CgptState test, finished.
586 """
587 return self._cgpt_state.test_loop()
588
589
590 def set_cgpt_test_step(self, step):
591 """Set the CgptState test step.
592
593 Args:
594 step: A test step number.
595 """
596 self._cgpt_state.set_step(step)
597
598
599 def get_cgpt_test_step(self):
600 """Get the CgptState test step.
601
602 Returns:
603 A test step number.
604 """
605 return self._cgpt_state.get_step()
606
607
ctchangc7e55ea2012-08-09 16:19:14 +0800608 def setup_firmwareupdate_temp_dir(self):
609 """Setup temporary directory.
610
611 Devkeys are copied to _key_path. Then, shellball,
612 /usr/sbin/chromeos-firmwareupdate, is extracted to _work_path.
613 """
ctchang6b700df2012-08-20 13:48:07 +0800614
615 self.cleanup_firmwareupdate_temp_dir()
616
ctchangc7e55ea2012-08-09 16:19:14 +0800617 os.mkdir(self._temp_path)
618 os.chdir(self._temp_path)
619
620 os.mkdir(self._work_path)
621 shutil.copytree('/usr/share/vboot/devkeys/', self._keys_path)
622 self.run_shell_command(
623 'sh /usr/sbin/chromeos-firmwareupdate --sb_extract %s'
624 % self._work_path)
625
626
627 def retrieve_shellball_fwid(self):
628 """Retrieve shellball's fwid.
629
630 This method should be called after setup_firmwareupdate_temp_dir.
631
632 Returns:
633 Shellball's fwid.
634 """
635 self.run_shell_command('dump_fmap -x %s %s' %
636 (os.path.join(self._work_path, 'bios.bin'),
637 'RW_FWID_A'))
638
639 [fwid] = self.run_shell_command_get_output(
ctchangcc88d112012-08-23 17:56:15 +0800640 "cat RW_FWID_A | tr '\\0' '\\t' | cut -f1")
ctchangc7e55ea2012-08-09 16:19:14 +0800641
642 return fwid
643
644
645 def cleanup_firmwareupdate_temp_dir(self):
646 """Cleanup temporary directory."""
ctchang6b700df2012-08-20 13:48:07 +0800647 if os.path.isdir(self._temp_path):
648 shutil.rmtree(self._temp_path)
ctchangc7e55ea2012-08-09 16:19:14 +0800649
650
651 def repack_firmwareupdate_shellball(self, append):
652 """Repack shellball with new fwid.
653
654 New fwid follows the rule: [orignal_fwid]-[append].
655
656 Args:
657 append: use for new fwid naming.
658 """
659 shutil.copy('/usr/sbin/chromeos-firmwareupdate', '%s' %
660 os.path.join(self._temp_path,
661 'chromeos-firmwareupdate-%s' % append))
662
ctchang6b700df2012-08-20 13:48:07 +0800663 self.run_shell_command('sh %s --sb_repack %s' % (
664 os.path.join(self._temp_path,
665 'chromeos-firmwareupdate-%s' % append),
666 self._work_path))
ctchangc7e55ea2012-08-09 16:19:14 +0800667
668 args = ['-i']
669 args.append('"s/TARGET_FWID=\\"\\(.*\\)\\"/TARGET_FWID=\\"\\1.%s\\"/g"'
670 % append)
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 args = ['-i']
678 args.append('"s/TARGET_UNSTABLE=\\".*\\"/TARGET_UNSTABLE=\\"\\"/g"')
679 args.append('%s'
680 % os.path.join(self._temp_path,
681 'chromeos-firmwareupdate-%s' % append))
682 cmd = 'sed %s' % ' '.join(args)
683 self.run_shell_command(cmd)
684
685
686 def resign_firmware(self, version):
687 """Resign firmware with version.
688
689 Args:
690 version: new firmware version number.
691 """
692 args = [os.path.join(self._work_path, 'bios.bin')]
693 args.append(os.path.join(self._temp_path, 'output.bin'))
694 args.append(os.path.join(self._keys_path, 'firmware_data_key.vbprivk'))
695 args.append(os.path.join(self._keys_path, 'firmware.keyblock'))
696 args.append(os.path.join(self._keys_path,
697 'dev_firmware_data_key.vbprivk'))
698 args.append(os.path.join(self._keys_path, 'dev_firmware.keyblock'))
699 args.append(os.path.join(self._keys_path, 'kernel_subkey.vbpubk'))
700 args.append('%d' % version)
701 args.append('1')
702 cmd = '/usr/share/vboot/bin/resign_firmwarefd.sh %s' % ' '.join(args)
703 self.run_shell_command(cmd)
704
705 shutil.copyfile('%s' % os.path.join(self._temp_path, 'output.bin'),
706 '%s' % os.path.join(self._work_path, 'bios.bin'))
707
708
709 def run_firmware_autoupdate(self, append):
710 """Do firmwareupdate with autoupdate mode using new shellball.
711
712 Args:
713 append: decide which shellball to use with format
714 chromeos-firmwareupdate-[append]
715 """
716 self.run_shell_command(
717 '/bin/sh %s --mode autoupdate --noupdate_ec'
718 % os.path.join(self._temp_path,
719 'chromeos-firmwareupdate-%s' % append))
720
721
722 def run_firmware_bootok(self, append):
723 """Do bootok mode using new shellball.
724
725 Copy firmware B to firmware A if reboot success.
726 """
727 self.run_shell_command(
728 '/bin/sh %s --mode bootok' % os.path.join(self._temp_path,
729 'chromeos-firmwareupdate-%s' % append))
730
731
732 def run_firmware_recovery(self):
733 """Recovery to original shellball."""
734 args = ['/usr/sbin/chromeos-firmwareupdate']
735 args.append('--mode recovery')
736 args.append('--noupdate_ec')
737 cmd = '/bin/sh %s' % ' '.join(args)
738 self.run_shell_command(cmd)
739
740
741 def get_temp_path(self):
742 """Get temporary directory path."""
743 return self._temp_path
744
745
ctchangcc88d112012-08-23 17:56:15 +0800746 def get_keys_path(self):
747 """Get keys path in temporary directory."""
748 return self._keys_path
749
750
751 def resign_kernel_with_keys(self, section, key_path=None):
752 """Resign kernel with temporary key."""
753 self._kernel_handler.resign_kernel(section, key_path)
754
755
Tom Wai-Hong Tambea57b32011-09-02 18:27:47 +0800756 def cleanup(self):
757 """Cleanup for the RPC server. Currently nothing."""
758 pass
759
760
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700761def main():
762 parser = OptionParser(usage='Usage: %prog [options]')
763 parser.add_option('--port', type='int', dest='port', default=9990,
764 help='port number of XMLRPC server')
765 (options, args) = parser.parse_args()
766
767 faft_client = FAFTClient()
768
769 # Launch the XMLRPC server to provide FAFTClient commands.
Tom Wai-Hong Tam4a257e52011-11-12 08:36:22 +0800770 server = SimpleXMLRPCServer(('localhost', options.port), allow_none=True,
771 logRequests=False)
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700772 server.register_introspection_functions()
773 server.register_instance(faft_client)
774 print 'XMLRPC Server: Serving FAFTClient on port %s' % options.port
775 server.serve_forever()
776
777
778if __name__ == '__main__':
779 main()