blob: 98a2024261c7a6f5703d0c114c8a0ea0d04efad5 [file] [log] [blame]
Tom Wai-Hong Tamc1e0b9a2012-11-01 13:52:39 +08001#!/usr/bin/python -u
barfab@chromium.orgb6d29932012-04-11 09:46:43 +02002# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -07003# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6"""Exposes the FAFTClient interface over XMLRPC.
7
8It launches a XMLRPC server and exposes the interface of FAFTClient object.
9The FAFTClient object aggreates some useful functions of exisintg SAFT
10libraries.
11"""
12
ctchang38ae4922012-09-03 17:01:16 +080013import functools, os, shutil, sys, tempfile
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -070014from optparse import OptionParser
15from SimpleXMLRPCServer import SimpleXMLRPCServer
16
Tom Wai-Hong Tamc0168912012-09-13 13:24:02 +080017from saft import cgpt_state, chromeos_interface, flashrom_handler
18from saft import kernel_handler, saft_flashrom_util, tpm_handler
Chun-ting Changcf924e92012-10-29 13:49:01 +080019from firmware_updater import FirmwareUpdater
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
Chun-ting Changd43aa9b2012-11-16 10:12:05 +080060 be accessed remotely. Method naming should fit the naming rule
61 '_[categories]_[method_name]' where categories contains system, ec, bios,
62 kernel, cgpt, tpm, updater, etc. Methods should be called by
63 'FAFTClient.[categories].[method_name]', because _dispatch will rename
64 this name to '_[categories]_[method_name]'.
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -070065
66 Attributes:
67 _chromeos_interface: An object to encapsulate OS services functions.
Vic Yang59cac9c2012-05-21 15:28:42 +080068 _bios_handler: An object to automate BIOS flashrom testing.
69 _ec_handler: An object to automate EC flashrom testing.
Tom Wai-Hong Tam23870e02012-08-24 16:15:34 +080070 _ec_image: An object to automate EC image for autest.
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -070071 _kernel_handler: An object to provide kernel related actions.
72 _tpm_handler: An object to control TPM device.
Chun-ting Changcf924e92012-10-29 13:49:01 +080073 _updater: An object to update firmware.
ctchangc7e55ea2012-08-09 16:19:14 +080074 _temp_path: Path of a temp directory.
75 _keys_path: Path of a directory, keys/, in temp directory.
76 _work_path: Path of a directory, work/, in temp directory.
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -070077 """
78
79 def __init__(self):
80 """Initialize the data attributes of this class."""
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -070081 # TODO(waihong): Move the explicit object.init() methods to the
82 # objects' constructors (ChromeOSInterface, FlashromHandler,
83 # KernelHandler, and TpmHandler).
84 self._chromeos_interface = chromeos_interface.ChromeOSInterface(False)
Tom Wai-Hong Tam48958832011-12-30 10:16:57 +080085 # We keep the state of FAFT test in a permanent directory over reboots.
Tom Wai-Hong Tam07278c22012-02-08 16:53:00 +080086 state_dir = '/var/tmp/faft'
87 self._chromeos_interface.init(state_dir, log_file='/tmp/faft_log.txt')
88 os.chdir(state_dir)
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -070089
Vic Yang13d22ec2012-06-18 15:12:47 +080090 self._bios_handler = LazyFlashromHandlerProxy(
91 saft_flashrom_util,
Vic Yang59cac9c2012-05-21 15:28:42 +080092 self._chromeos_interface,
93 None,
94 '/usr/share/vboot/devkeys',
95 'bios')
Vic Yang59cac9c2012-05-21 15:28:42 +080096
Todd Brochf2b1d012012-06-14 12:55:21 -070097 self._ec_handler = None
98 if not os.system("mosys ec info"):
Vic Yang13d22ec2012-06-18 15:12:47 +080099 self._ec_handler = LazyFlashromHandlerProxy(
100 saft_flashrom_util,
Todd Brochf2b1d012012-06-14 12:55:21 -0700101 self._chromeos_interface,
Vic Yang13d22ec2012-06-18 15:12:47 +0800102 'ec_root_key.vpubk',
Todd Brochf2b1d012012-06-14 12:55:21 -0700103 '/usr/share/vboot/devkeys',
104 'ec')
Todd Brochf2b1d012012-06-14 12:55:21 -0700105
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700106
107 self._kernel_handler = kernel_handler.KernelHandler()
Tom Wai-Hong Tam07278c22012-02-08 16:53:00 +0800108 # TODO(waihong): The dev_key_path is a new argument. We do that in
109 # order not to break the old image and still be able to run.
110 try:
111 self._kernel_handler.init(self._chromeos_interface,
ctchangd60030f2012-08-29 15:39:56 +0800112 dev_key_path='/usr/share/vboot/devkeys',
113 internal_disk=True)
Tom Wai-Hong Tam07278c22012-02-08 16:53:00 +0800114 except:
115 # Copy the key to the current working directory.
116 shutil.copy('/usr/share/vboot/devkeys/kernel_data_key.vbprivk', '.')
ctchangd60030f2012-08-29 15:39:56 +0800117 self._kernel_handler.init(self._chromeos_interface,
118 internal_disk=True)
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700119
120 self._tpm_handler = tpm_handler.TpmHandler()
121 self._tpm_handler.init(self._chromeos_interface)
122
Tom Wai-Hong Tam48958832011-12-30 10:16:57 +0800123 self._cgpt_state = cgpt_state.CgptState(
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800124 'SHORT', self._chromeos_interface, self._system_get_root_dev())
Tom Wai-Hong Tam48958832011-12-30 10:16:57 +0800125
Chun-ting Changcf924e92012-10-29 13:49:01 +0800126 self._updater = FirmwareUpdater(self._chromeos_interface)
127
128
ctchangc7e55ea2012-08-09 16:19:14 +0800129 # Initialize temporary directory path
130 self._temp_path = '/var/tmp/faft/autest'
131 self._keys_path = os.path.join(self._temp_path, 'keys')
132 self._work_path = os.path.join(self._temp_path, 'work')
133
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700134
Tom Wai-Hong Tame8f291a2011-12-08 22:03:53 +0800135 def _dispatch(self, method, params):
136 """This _dispatch method handles string conversion especially.
137
138 Since we turn off allow_dotted_names option. So any string conversion,
139 like str(FAFTClient.method), i.e. FAFTClient.method.__str__, failed
140 via XML RPC call.
141 """
142 is_str = method.endswith('.__str__')
143 if is_str:
144 method = method.rsplit('.', 1)[0]
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800145
146 categories = ('system', 'bios', 'ec', 'kernel',
147 'tpm', 'cgpt', 'updater')
Tom Wai-Hong Tame8f291a2011-12-08 22:03:53 +0800148 try:
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800149 if method.split('.', 1)[0] in categories:
150 func = getattr(self, '_%s_%s' % (method.split('.',1)[0],
151 method.split('.',1)[1]))
152 else:
153 func = getattr(self, method)
Tom Wai-Hong Tame8f291a2011-12-08 22:03:53 +0800154 except AttributeError:
155 raise Exception('method "%s" is not supported' % method)
156 else:
157 if is_str:
158 return str(func)
159 else:
160 return func(*params)
161
162
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800163 def _system_is_available(self):
Tom Wai-Hong Tambea57b32011-09-02 18:27:47 +0800164 """Function for polling the RPC server availability.
165
166 Returns:
167 Always True.
168 """
169 return True
170
171
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800172 def _system_run_shell_command(self, command):
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700173 """Run shell command.
174
175 Args:
176 command: A shell command to be run.
177 """
178 self._chromeos_interface.log('Requesting run shell command')
179 self._chromeos_interface.run_shell_command(command)
180
181
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800182 def _system_run_shell_command_get_output(self, command):
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700183 """Run shell command and get its console output.
184
185 Args:
186 command: A shell command to be run.
187
188 Returns:
189 A list of strings stripped of the newline characters.
190 """
191 self._chromeos_interface.log(
192 'Requesting run shell command and get its console output')
193 return self._chromeos_interface.run_shell_command_get_output(command)
194
195
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800196 def _system_software_reboot(self):
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700197 """Request software reboot."""
198 self._chromeos_interface.log('Requesting software reboot')
199 self._chromeos_interface.run_shell_command('reboot')
200
201
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800202 def _system_get_platform_name(self):
Tom Wai-Hong Tam678ab152011-12-14 15:27:24 +0800203 """Get the platform name of the current system.
204
205 Returns:
206 A string of the platform name.
207 """
208 self._chromeos_interface.log('Requesting get platform name')
Vic Yang2bbb8672012-11-12 12:14:53 +0800209 # 'mosys platform name' sometimes fails. Let's get the verbose output.
210 lines = self._chromeos_interface.run_shell_command_get_output(
211 '(mosys -vvv platform name 2>&1) || echo Failed')
212 if lines[-1].strip() == 'Failed':
213 raise Exception('Failed getting platform name: ' + '\n'.join(lines))
214 return lines[-1]
Tom Wai-Hong Tam678ab152011-12-14 15:27:24 +0800215
216
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800217 def _system_get_crossystem_value(self, key):
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700218 """Get crossystem value of the requested key.
219
220 Args:
221 key: A crossystem key.
222
223 Returns:
224 A string of the requested crossystem value.
225 """
226 self._chromeos_interface.log('Requesting get crossystem value')
227 return self._chromeos_interface.run_shell_command_get_output(
228 'crossystem %s' % key)[0]
229
230
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800231 def _ec_get_version(self):
Tom Wai-Hong Tamb92669c2012-11-29 13:57:11 +0800232 """Get EC version via mosys.
233
234 Returns:
235 A string of the EC version.
236 """
237 self._chromeos_interface.log('Requesting get EC version')
238 return self._chromeos_interface.run_shell_command_get_output(
239 'mosys ec info | sed "s/.*| //"')[0]
240
241
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800242 def _system_get_root_dev(self):
Tom Wai-Hong Tamcfda61f2011-11-02 17:41:01 +0800243 """Get the name of root device without partition number.
244
245 Returns:
246 A string of the root device without partition number.
247 """
248 self._chromeos_interface.log('Requesting get root device')
249 return self._chromeos_interface.get_root_dev()
250
251
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800252 def _system_get_root_part(self):
Tom Wai-Hong Tamcfda61f2011-11-02 17:41:01 +0800253 """Get the name of root device with partition number.
254
255 Returns:
256 A string of the root device with partition number.
257 """
258 self._chromeos_interface.log('Requesting get root part')
259 return self._chromeos_interface.get_root_part()
260
261
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800262 def _system_set_try_fw_b(self):
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700263 """Set 'Try Frimware B' flag in crossystem."""
264 self._chromeos_interface.log('Requesting restart with firmware B')
265 self._chromeos_interface.cs.fwb_tries = 1
266
267
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800268 def _system_request_recovery_boot(self):
Tom Wai-Hong Tam76c75072011-10-25 18:00:12 +0800269 """Request running in recovery mode on the restart."""
270 self._chromeos_interface.log('Requesting restart in recovery mode')
271 self._chromeos_interface.cs.request_recovery()
272
273
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800274 def _system_get_dev_boot_usb(self):
Tom Wai-Hong Tam0a7b2be2012-10-15 16:44:12 +0800275 """Get dev_boot_usb value which controls developer mode boot from USB.
276
277 Returns:
278 True if enable, False if disable.
279 """
280 self._chromeos_interface.log('Getting dev_boot_usb')
281 return self._chromeos_interface.cs.dev_boot_usb == '1'
282
283
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800284 def _system_set_dev_boot_usb(self, value):
Tom Wai-Hong Tam0a7b2be2012-10-15 16:44:12 +0800285 """Set dev_boot_usb value which controls developer mode boot from USB.
286
287 Args:
288 value: True to enable, False to disable.
289 """
290 self._chromeos_interface.log('Setting dev_boot_usb to %s' % str(value))
291 self._chromeos_interface.cs.dev_boot_usb = 1 if value else 0
292
293
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800294 def _system_get_gbb_flags(self):
Tom Wai-Hong Tam8c9eed62011-12-28 15:05:05 +0800295 """Get the GBB flags.
296
297 Returns:
298 An integer of the GBB flags.
299 """
300 self._chromeos_interface.log('Getting GBB flags')
Vic Yang59cac9c2012-05-21 15:28:42 +0800301 return self._bios_handler.get_gbb_flags()
Tom Wai-Hong Tam8c9eed62011-12-28 15:05:05 +0800302
303
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800304 def _bios_get_preamble_flags(self, section):
Tom Wai-Hong Tam81f70002011-12-13 12:29:46 +0800305 """Get the preamble flags of a firmware section.
306
307 Args:
308 section: A firmware section, either 'a' or 'b'.
309
310 Returns:
311 An integer of the preamble flags.
312 """
313 self._chromeos_interface.log('Getting preamble flags of firmware %s' %
314 section)
Vic Yang59cac9c2012-05-21 15:28:42 +0800315 return self._bios_handler.get_section_flags(section)
316
317
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800318 def _bios_set_preamble_flags(self, section, flags):
Vic Yang91b73cf2012-07-31 17:18:11 +0800319 """Set the preamble flags of a firmware section.
320
321 Args:
322 section: A firmware section, either 'a' or 'b'.
323 flags: An integer of preamble flags.
324 """
325 self._chromeos_interface.log(
326 'Setting preamble flags of firmware %s to %s' % (section, flags))
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800327 version = self._bios_get_version(section)
Vic Yang91b73cf2012-07-31 17:18:11 +0800328 self._bios_handler.set_section_version(section, version, flags,
329 write_through=True)
330
331
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800332 def _bios_get_body_sha(self, section):
Tom Wai-Hong Tam4e10b9f2012-09-06 16:23:02 +0800333 """Get SHA1 hash of BIOS RW firmware section.
334
335 Args:
336 section: A firmware section, either 'a' or 'b'.
337 flags: An integer of preamble flags.
338 """
339 return self._bios_handler.get_section_sha(section)
340
341
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800342 def _bios_get_sig_sha(self, section):
ctchang38ae4922012-09-03 17:01:16 +0800343 """Get SHA1 hash of firmware vblock in section."""
344 return self._bios_handler.get_section_sig_sha(section)
345
346
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800347 def _ec_get_firmware_sha(self):
Tom Wai-Hong Tam4e10b9f2012-09-06 16:23:02 +0800348 """Get SHA1 hash of EC RW firmware section."""
Vic Yang91b73cf2012-07-31 17:18:11 +0800349 return self._ec_handler.get_section_sha('rw')
350
351
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800352 def _bios_reload(self):
Tom Wai-Hong Tamc1c4deb2012-07-26 14:28:11 +0800353 """Reload the firmware image that may be changed."""
354 self._bios_handler.reload()
355
356
Vic Yang59cac9c2012-05-21 15:28:42 +0800357 @allow_multiple_section_input
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800358 def _ec_corrupt_sig(self, section):
Vic Yang59cac9c2012-05-21 15:28:42 +0800359 """Corrupt the requested EC section signature.
360
361 Args:
362 section: A EC section, either 'a' or 'b'.
363 """
364 self._chromeos_interface.log('Corrupting EC signature %s' %
365 section)
Vic Yang37a55462012-06-29 14:00:28 +0800366 self._ec_handler.corrupt_firmware(section, corrupt_all=True)
Vic Yang59cac9c2012-05-21 15:28:42 +0800367
368
369 @allow_multiple_section_input
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800370 def _ec_corrupt_body(self, section):
Vic Yang59cac9c2012-05-21 15:28:42 +0800371 """Corrupt the requested EC section body.
372
373 Args:
374 section: An EC section, either 'a' or 'b'.
375 """
376 self._chromeos_interface.log('Corrupting EC body %s' %
377 section)
Vic Yang37a55462012-06-29 14:00:28 +0800378 self._ec_handler.corrupt_firmware_body(section, corrupt_all=True)
Vic Yang59cac9c2012-05-21 15:28:42 +0800379
380
381 @allow_multiple_section_input
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800382 def _ec_restore_sig(self, section):
Vic Yang59cac9c2012-05-21 15:28:42 +0800383 """Restore the previously corrupted EC section signature.
384
385 Args:
386 section: An EC section, either 'a' or 'b'.
387 """
388 self._chromeos_interface.log('Restoring EC signature %s' %
389 section)
Vic Yang37a55462012-06-29 14:00:28 +0800390 self._ec_handler.restore_firmware(section, restore_all=True)
Vic Yang59cac9c2012-05-21 15:28:42 +0800391
392
393 @allow_multiple_section_input
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800394 def _ec_restore_body(self, section):
Vic Yang59cac9c2012-05-21 15:28:42 +0800395 """Restore the previously corrupted EC section body.
396
397 Args:
398 section: An EC section, either 'a' or 'b'.
399 """
400 self._chromeos_interface.log('Restoring EC body %s' %
401 section)
Vic Yang37a55462012-06-29 14:00:28 +0800402 self._ec_handler.restore_firmware_body(section, restore_all=True)
Tom Wai-Hong Tam81f70002011-12-13 12:29:46 +0800403
404
Tom Wai-Hong Tam0e680af2011-10-26 14:32:55 +0800405 @allow_multiple_section_input
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800406 def _bios_corrupt_sig(self, section):
Tom Wai-Hong Tam9aea8212011-12-12 15:08:45 +0800407 """Corrupt the requested firmware section signature.
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700408
409 Args:
410 section: A firmware section, either 'a' or 'b'.
411 """
Tom Wai-Hong Tam9aea8212011-12-12 15:08:45 +0800412 self._chromeos_interface.log('Corrupting firmware signature %s' %
413 section)
Vic Yang59cac9c2012-05-21 15:28:42 +0800414 self._bios_handler.corrupt_firmware(section)
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700415
416
Tom Wai-Hong Tam0e680af2011-10-26 14:32:55 +0800417 @allow_multiple_section_input
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800418 def _bios_corrupt_body(self, section):
Tom Wai-Hong Tam81f70002011-12-13 12:29:46 +0800419 """Corrupt the requested firmware section body.
420
421 Args:
422 section: A firmware section, either 'a' or 'b'.
423 """
424 self._chromeos_interface.log('Corrupting firmware body %s' %
425 section)
Vic Yang59cac9c2012-05-21 15:28:42 +0800426 self._bios_handler.corrupt_firmware_body(section)
Tom Wai-Hong Tam81f70002011-12-13 12:29:46 +0800427
428
429 @allow_multiple_section_input
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800430 def _bios_restore_sig(self, section):
Tom Wai-Hong Tam9aea8212011-12-12 15:08:45 +0800431 """Restore the previously corrupted firmware section signature.
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700432
433 Args:
434 section: A firmware section, either 'a' or 'b'.
435 """
Tom Wai-Hong Tam9aea8212011-12-12 15:08:45 +0800436 self._chromeos_interface.log('Restoring firmware signature %s' %
437 section)
Vic Yang59cac9c2012-05-21 15:28:42 +0800438 self._bios_handler.restore_firmware(section)
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700439
440
Tom Wai-Hong Tamcfda61f2011-11-02 17:41:01 +0800441 @allow_multiple_section_input
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800442 def _bios_restore_body(self, section):
Tom Wai-Hong Tam81f70002011-12-13 12:29:46 +0800443 """Restore the previously corrupted firmware section body.
444
445 Args:
446 section: A firmware section, either 'a' or 'b'.
447 """
448 self._chromeos_interface.log('Restoring firmware body %s' %
449 section)
Vic Yang59cac9c2012-05-21 15:28:42 +0800450 self._bios_handler.restore_firmware_body(section)
Tom Wai-Hong Tam81f70002011-12-13 12:29:46 +0800451
452
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800453 def _bios_get_version(self, section):
Vic Yang91b73cf2012-07-31 17:18:11 +0800454 """Retrieve firmware version of a section."""
455 return self._bios_handler.get_section_version(section)
456
457
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800458 def _tpm_get_firmware_version(self):
Chun-ting Changa4f65532012-10-17 16:57:28 +0800459 """Retrieve tpm firmware body version."""
460 return self._tpm_handler.get_fw_version()
461
462
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800463 def __bios_modify_version(self, section, delta):
Tom Wai-Hong Tam46d03b12012-02-08 12:02:17 +0800464 """Modify firmware version for the requested section, by adding delta.
465
466 The passed in delta, a positive or a negative number, is added to the
467 original firmware version.
468 """
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800469 original_version = self._bios_get_version(section)
Tom Wai-Hong Tam46d03b12012-02-08 12:02:17 +0800470 new_version = original_version + delta
Vic Yang59cac9c2012-05-21 15:28:42 +0800471 flags = self._bios_handler.get_section_flags(section)
Tom Wai-Hong Tam46d03b12012-02-08 12:02:17 +0800472 self._chromeos_interface.log(
473 'Setting firmware section %s version from %d to %d' % (
474 section, original_version, new_version))
Vic Yang59cac9c2012-05-21 15:28:42 +0800475 self._bios_handler.set_section_version(section, new_version, flags,
476 write_through=True)
Tom Wai-Hong Tam46d03b12012-02-08 12:02:17 +0800477
478 @allow_multiple_section_input
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800479 def _bios_move_version_backward(self, section):
Tom Wai-Hong Tam46d03b12012-02-08 12:02:17 +0800480 """Decrement firmware version for the requested section."""
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800481 self.__bios_modify_version(section, -1)
Tom Wai-Hong Tam46d03b12012-02-08 12:02:17 +0800482
483
484 @allow_multiple_section_input
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800485 def _bios_move_version_forward(self, section):
Tom Wai-Hong Tam46d03b12012-02-08 12:02:17 +0800486 """Increase firmware version for the requested section."""
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800487 self.__bios_modify_version(section, 1)
Tom Wai-Hong Tam46d03b12012-02-08 12:02:17 +0800488
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800489 def _bios_get_datakey_version(self, section):
ctchangc7e55ea2012-08-09 16:19:14 +0800490 """Return firmware data key version."""
491 return self._bios_handler.get_section_datakey_version(section)
492
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800493 def _tpm_get_firmware_datakey_version(self):
Chun-ting Changa4f65532012-10-17 16:57:28 +0800494 """Retrieve tpm firmware data key version."""
495 return self._tpm_handler.get_fw_body_version()
496
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800497 def _bios_get_kernel_subkey_version(self,section):
ctchangc7e55ea2012-08-09 16:19:14 +0800498 """Return kernel subkey version."""
499 return self._bios_handler.get_section_kernel_subkey_version(section)
Tom Wai-Hong Tam46d03b12012-02-08 12:02:17 +0800500
Tom Wai-Hong Tam81f70002011-12-13 12:29:46 +0800501 @allow_multiple_section_input
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800502 def _kernel_corrupt_sig(self, section):
Tom Wai-Hong Tamcfda61f2011-11-02 17:41:01 +0800503 """Corrupt the requested kernel section.
504
505 Args:
506 section: A kernel section, either 'a' or 'b'.
507 """
508 self._chromeos_interface.log('Corrupting kernel %s' % section)
509 self._kernel_handler.corrupt_kernel(section)
510
511
512 @allow_multiple_section_input
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800513 def _kernel_restore_sig(self, section):
Tom Wai-Hong Tamcfda61f2011-11-02 17:41:01 +0800514 """Restore the requested kernel section (previously corrupted).
515
516 Args:
517 section: A kernel section, either 'a' or 'b'.
518 """
Tom Wai-Hong Tamcfda61f2011-11-02 17:41:01 +0800519 self._kernel_handler.restore_kernel(section)
520
521
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800522 def __kernel_modify_version(self, section, delta):
Tom Wai-Hong Tam07278c22012-02-08 16:53:00 +0800523 """Modify kernel version for the requested section, by adding delta.
524
525 The passed in delta, a positive or a negative number, is added to the
526 original kernel version.
527 """
528 original_version = self._kernel_handler.get_version(section)
529 new_version = original_version + delta
530 self._chromeos_interface.log(
531 'Setting kernel section %s version from %d to %d' % (
532 section, original_version, new_version))
533 self._kernel_handler.set_version(section, new_version)
534
535
536 @allow_multiple_section_input
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800537 def _kernel_move_version_backward(self, section):
Tom Wai-Hong Tam07278c22012-02-08 16:53:00 +0800538 """Decrement kernel version for the requested section."""
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800539 self.__kernel_modify_version(section, -1)
Tom Wai-Hong Tam07278c22012-02-08 16:53:00 +0800540
541
542 @allow_multiple_section_input
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800543 def _kernel_move_version_forward(self, section):
Tom Wai-Hong Tam07278c22012-02-08 16:53:00 +0800544 """Increase kernel version for the requested section."""
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800545 self.__kernel_modify_version(section, 1)
Tom Wai-Hong Tam07278c22012-02-08 16:53:00 +0800546
ctchangcc88d112012-08-23 17:56:15 +0800547
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800548 def _kernel_get_version(self, section):
ctchangcc88d112012-08-23 17:56:15 +0800549 """Return kernel version."""
550 return self._kernel_handler.get_version(section)
551
552
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800553 def _kernel_get_datakey_version(self, section):
ctchangcc88d112012-08-23 17:56:15 +0800554 """Return kernel datakey version."""
555 return self._kernel_handler.get_datakey_version(section)
556
557
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800558 def _kernel_diff_a_b(self):
Tom Wai-Hong Tam622d0ba2012-08-15 16:29:05 +0800559 """Compare kernel A with B.
560
561 Returns:
562 True: if kernel A is different with B.
563 False: if kernel A is the same as B.
564 """
565 rootdev = self._chromeos_interface.get_root_dev()
566 kernel_a = self._chromeos_interface.join_part(rootdev, '3')
567 kernel_b = self._chromeos_interface.join_part(rootdev, '5')
568
569 # The signature (some kind of hash) for the kernel body is stored in
570 # the beginning. So compare the first 64KB (including header, preamble,
571 # and signature) should be enough to check them identical.
572 header_a = self._chromeos_interface.read_partition(kernel_a, 0x10000)
573 header_b = self._chromeos_interface.read_partition(kernel_b, 0x10000)
574
575 return header_a != header_b
Tom Wai-Hong Tam07278c22012-02-08 16:53:00 +0800576
Tom Wai-Hong Tam23870e02012-08-24 16:15:34 +0800577
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800578 def _system_is_removable_device_boot(self):
Tom Wai-Hong Tam0a7b2be2012-10-15 16:44:12 +0800579 """Check the current boot device is removable.
580
581 Returns:
582 True: if a removable device boots.
583 False: if a non-removable device boots.
584 """
585 root_part = self._chromeos_interface.get_root_part()
586 return self._chromeos_interface.is_removable_device(root_part)
587
588
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800589 def _bios_setup_EC_image(self, ec_path):
Tom Wai-Hong Tam23870e02012-08-24 16:15:34 +0800590 """Setup the new EC image for later update.
591
592 Args:
593 ec_path: The path of the EC image to be updated.
594 """
595 self._ec_image = flashrom_handler.FlashromHandler()
596 self._ec_image.init(saft_flashrom_util,
597 self._chromeos_interface,
598 'ec_root_key.vpubk',
599 '/usr/share/vboot/devkeys',
600 'ec')
601 self._ec_image.new_image(ec_path)
602
603
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800604 def _bios_get_EC_image_sha(self):
Tom Wai-Hong Tam23870e02012-08-24 16:15:34 +0800605 """Get SHA1 hash of RW firmware section of the EC autest image."""
606 return self._ec_image.get_section_sha('rw')
607
608
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800609 def _bios_update_EC_from_image(self, section, flags):
Tom Wai-Hong Tam23870e02012-08-24 16:15:34 +0800610 """Update EC via software sync design.
611
612 It copys the RW section from the EC image, which is loaded by calling
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800613 bios_setup_EC_image(), to the EC area of the specified RW section on the
Tom Wai-Hong Tam23870e02012-08-24 16:15:34 +0800614 current AP firmware.
615
616 Args:
617 section: A firmware section on current BIOS, either 'a' or 'b'.
618 flags: An integer of preamble flags.
619 """
620 blob = self._ec_image.get_section_body('rw')
621 self._bios_handler.set_section_ecbin(section, blob,
622 write_through=True)
623 self.set_firmware_flags(section, flags)
624
625
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800626 def _bios_dump_whole(self, bios_path):
Tom Wai-Hong Tamb63bc742012-08-30 20:41:30 +0800627 """Dump the current BIOS firmware to a file, specified by bios_path.
628
629 Args:
630 bios_path: The path of the BIOS image to be written.
631 """
632 self._bios_handler.dump_whole(bios_path)
633
634
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800635 def _bios_dump_rw(self, dir_path):
ctchang38ae4922012-09-03 17:01:16 +0800636 """Dump the current BIOS firmware RW to dir_path.
637
638 VBOOTA, VBOOTB, FVMAIN, FVMAINB need to be dumped.
639
640 Args:
641 dir_path: The path of directory which contains files to be written.
642 """
643 if not os.path.isdir(dir_path):
644 raise Exception("%s doesn't exist" % dir_path)
645
646 VBOOTA_blob = self._bios_handler.get_section_sig('a')
647 VBOOTB_blob = self._bios_handler.get_section_sig('b')
648 FVMAIN_blob = self._bios_handler.get_section_body('a')
649 FVMAINB_blob = self._bios_handler.get_section_body('b')
650
651 open(os.path.join(dir_path, 'VBOOTA'), 'w').write(VBOOTA_blob)
652 open(os.path.join(dir_path, 'VBOOTB'), 'w').write(VBOOTB_blob)
653 open(os.path.join(dir_path, 'FVMAIN'), 'w').write(FVMAIN_blob)
654 open(os.path.join(dir_path, 'FVMAINB'), 'w').write(FVMAINB_blob)
655
656
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800657 def _bios_write_whole(self, bios_path):
Tom Wai-Hong Tamb63bc742012-08-30 20:41:30 +0800658 """Write the firmware from bios_path to the current system.
659
660 Args:
661 bios_path: The path of the source BIOS image.
662 """
663 self._bios_handler.new_image(bios_path)
664 self._bios_handler.write_whole()
665
666
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800667 def _bios_write_rw(self, dir_path):
ctchang38ae4922012-09-03 17:01:16 +0800668 """Write the firmware RW from dir_path to the current system.
669
670 VBOOTA, VBOOTB, FVMAIN, FVMAINB need to be written.
671
672 Args:
673 dir_path: The path of directory which contains the source files.
674 """
675 if not os.path.exists(os.path.join(dir_path, 'VBOOTA')) or \
676 not os.path.exists(os.path.join(dir_path, 'VBOOTB')) or \
677 not os.path.exists(os.path.join(dir_path, 'FVMAIN')) or \
678 not os.path.exists(os.path.join(dir_path, 'FVMAINB')):
679 raise Exception("Source firmware file(s) doesn't exist.")
680
681 VBOOTA_blob = open(os.path.join(dir_path, 'VBOOTA'), 'rb').read()
682 VBOOTB_blob = open(os.path.join(dir_path, 'VBOOTB'), 'rb').read()
683 FVMAIN_blob = open(os.path.join(dir_path, 'FVMAIN'), 'rb').read()
684 FVMAINB_blob = open(os.path.join(dir_path, 'FVMAINB'), 'rb').read()
685
686 self._bios_handler.set_section_sig('a', VBOOTA_blob,
687 write_through=True)
688 self._bios_handler.set_section_sig('b', VBOOTB_blob,
689 write_through=True)
690 self._bios_handler.set_section_body('a', FVMAIN_blob,
691 write_through=True)
692 self._bios_handler.set_section_body('b', FVMAINB_blob,
693 write_through=True)
694
695
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800696 def _ec_dump_firmware(self, ec_path):
Tom Wai-Hong Tam23870e02012-08-24 16:15:34 +0800697 """Dump the current EC firmware to a file, specified by ec_path.
698
699 Args:
700 ec_path: The path of the EC image to be written.
701 """
702 self._ec_handler.dump_whole(ec_path)
703
704
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800705 def _ec_set_write_protect(self, enable):
Tom Wai-Hong Tam44204b32012-11-20 13:55:40 +0800706 """Enable write protect of the EC flash chip.
707
708 Args:
709 enable: True if activating EC write protect. Otherwise, False.
710 """
711 self._chromeos_interface.log('Requesting set EC write protect to %s' %
712 ('enable' if enable else 'disable'))
713 if enable:
714 self._ec_handler.enable_write_protect()
715 else:
716 self._ec_handler.disable_write_protect()
717
718
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800719 def _cgpt_run_test_loop(self):
Tom Wai-Hong Tam48958832011-12-30 10:16:57 +0800720 """Run the CgptState test loop. The tst logic is handled in the client.
721
722 Returns:
723 0: there are more cgpt tests to execute.
724 1: no more CgptState test, finished.
725 """
726 return self._cgpt_state.test_loop()
727
728
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800729 def _cgpt_set_test_step(self, step):
Tom Wai-Hong Tam48958832011-12-30 10:16:57 +0800730 """Set the CgptState test step.
731
732 Args:
733 step: A test step number.
734 """
735 self._cgpt_state.set_step(step)
736
737
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800738 def _cgpt_get_test_step(self):
Tom Wai-Hong Tam48958832011-12-30 10:16:57 +0800739 """Get the CgptState test step.
740
741 Returns:
742 A test step number.
743 """
744 return self._cgpt_state.get_step()
745
746
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800747 def _kernel_resign_with_keys(self, section, key_path=None):
ctchangcc88d112012-08-23 17:56:15 +0800748 """Resign kernel with temporary key."""
749 self._kernel_handler.resign_kernel(section, key_path)
750
751
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800752 def _system_create_temp_dir(self, prefix='backup_'):
ctchang38ae4922012-09-03 17:01:16 +0800753 """Create a temporary directory and return the path."""
754 return tempfile.mkdtemp(prefix=prefix)
755
756
Chun-ting Changcf924e92012-10-29 13:49:01 +0800757 # for updater
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800758 def _updater_setup(self, shellball=None):
Chun-ting Changcf924e92012-10-29 13:49:01 +0800759 """Setup the updater.
760
761 Args:
762 shellball: Path of provided shellball. Use default shellball
763 if None,
764 """
765 self._updater.setup(self._chromeos_interface, shellball)
766
767
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800768 def _updater_cleanup(self):
Chun-ting Changcf924e92012-10-29 13:49:01 +0800769 self._updater.cleanup_temp_dir()
770
771
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800772 def _updater_get_fwid(self):
Chun-ting Changcf924e92012-10-29 13:49:01 +0800773 """Retrieve shellball's fwid.
774
775 This method should be called after updater_setup.
776
777 Returns:
778 Shellball's fwid.
779 """
780 return self._updater.retrieve_fwid()
781
782
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800783 def _updater_resign_firmware(self, version):
Chun-ting Changcf924e92012-10-29 13:49:01 +0800784 """Resign firmware with version.
785
786 Args:
787 version: new version number.
788 """
789 self._updater.resign_firmware(version)
790
791
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800792 def _updater_repack_shellball(self, append):
Chun-ting Changcf924e92012-10-29 13:49:01 +0800793 """Repack shellball with new fwid.
794
795 Args:
796 append: use for new fwid naming.
797 """
798 self._updater.repack_shellball(append)
799
800
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800801 def _updater_run_autoupdate(self, append):
Chun-ting Changcf924e92012-10-29 13:49:01 +0800802 """Run chromeos-firmwareupdate with autoupdate mode."""
803 options = ['--noupdate_ec', '--nocheck_rw_compatible']
804 self._updater.run_firmwareupdate(mode='autoupdate',
805 updater_append=append,
806 options=options)
807
808
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800809 def _updater_run_factory_install(self):
Chun-ting Changcf924e92012-10-29 13:49:01 +0800810 """Run chromeos-firmwareupdate with factory_install mode."""
811 options = ['--noupdate_ec']
812 self._updater.run_firmwareupdate(mode='factory_install',
813 options=options)
814
815
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800816 def _updater_run_bootok(self, append):
Chun-ting Changcf924e92012-10-29 13:49:01 +0800817 """Run chromeos-firmwareupdate with bootok mode."""
818 self._updater.run_firmwareupdate(mode='bootok',
819 updater_append=append)
820
821
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800822 def _updater_run_recovery(self):
Chun-ting Changcf924e92012-10-29 13:49:01 +0800823 """Run chromeos-firmwareupdate with recovery mode."""
824 options = ['--noupdate_ec', '--nocheck_rw_compatible']
825 self._updater.run_firmwareupdate(mode='recovery',
826 options=options)
827
828
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800829 def _updater_get_temp_path(self):
Chun-ting Changcf924e92012-10-29 13:49:01 +0800830 """Get updater's temp directory path."""
831 return self._updater.get_temp_path()
832
833
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800834 def _updater_get_keys_path(self):
Chun-ting Changcf924e92012-10-29 13:49:01 +0800835 """Get updater's keys directory path."""
836 return self._updater.get_keys_path()
837
838
Chun-ting Changd43aa9b2012-11-16 10:12:05 +0800839 def _updater_get_work_path(self):
Chun-ting Changcf924e92012-10-29 13:49:01 +0800840 """Get updater's work directory path."""
841 return self._updater.get_work_path()
842
843
Tom Wai-Hong Tambea57b32011-09-02 18:27:47 +0800844 def cleanup(self):
845 """Cleanup for the RPC server. Currently nothing."""
846 pass
847
848
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700849def main():
850 parser = OptionParser(usage='Usage: %prog [options]')
851 parser.add_option('--port', type='int', dest='port', default=9990,
852 help='port number of XMLRPC server')
853 (options, args) = parser.parse_args()
854
855 faft_client = FAFTClient()
856
857 # Launch the XMLRPC server to provide FAFTClient commands.
Tom Wai-Hong Tam4a257e52011-11-12 08:36:22 +0800858 server = SimpleXMLRPCServer(('localhost', options.port), allow_none=True,
Tom Wai-Hong Tamc1e0b9a2012-11-01 13:52:39 +0800859 logRequests=True)
Tom Wai-Hong Tamb8a58ef2011-10-11 23:53:10 -0700860 server.register_introspection_functions()
861 server.register_instance(faft_client)
862 print 'XMLRPC Server: Serving FAFTClient on port %s' % options.port
863 server.serve_forever()
864
865
866if __name__ == '__main__':
867 main()