Reorganizing FAFT client side code.
Created faft packages. Moved old saft modules into faft/utils. This is the
initial reorg step, and file/object names will be cleaned up in subsequent CLs.
Added a common.py which is necessary for setting up the autotest package
namespace.
BUG=None
TEST=Manually ran firmware_FAFTSetup at desk
Change-Id: I631b4457ad47cc15bfb9e3d915d75e648cb3d8f9
Reviewed-on: https://gerrit.chromium.org/gerrit/65614
Reviewed-by: Dennis Jeffrey <dennisjeffrey@chromium.org>
Commit-Queue: Yusuf Mohsinally <mohsinally@chromium.org>
Tested-by: Yusuf Mohsinally <mohsinally@chromium.org>
diff --git a/client/cros/faft/faft_client.py b/client/cros/faft/faft_client.py
new file mode 100755
index 0000000..e43bbb4
--- /dev/null
+++ b/client/cros/faft/faft_client.py
@@ -0,0 +1,746 @@
+#!/usr/bin/python -u
+# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Exposes the FAFTClient interface over XMLRPC.
+
+It launches a XMLRPC server and exposes the interface of FAFTClient object.
+The FAFTClient object aggreates some useful functions of exisintg SAFT
+libraries.
+"""
+
+import functools, os, shutil, tempfile
+from optparse import OptionParser
+from SimpleXMLRPCServer import SimpleXMLRPCServer
+
+import common
+from autotest_lib.client.cros.faft.utils import (cgpt_state,
+ chromeos_interface,
+ firmware_updater,
+ flashrom_handler,
+ kernel_handler,
+ saft_flashrom_util,
+ tpm_handler,
+ )
+
+
+def allow_multiple_section_input(image_operator):
+ """Decorate a method to support multiple sections.
+
+ @param image_operator: Method accepting one section as its argument.
+ """
+ @functools.wraps(image_operator)
+ def wrapper(self, section):
+ """Wrapper method to support multiple sections.
+
+ @param section: A list of sections of just a section.
+ """
+ if type(section) in (tuple, list):
+ for sec in section:
+ image_operator(self, sec)
+ else:
+ image_operator(self, section)
+ return wrapper
+
+
+class LazyFlashromHandlerProxy:
+ """Proxy of FlashromHandler for lazy initialization."""
+ _loaded = False
+ _obj = None
+
+ def __init__(self, *args, **kargs):
+ self._args = args
+ self._kargs = kargs
+
+ def _load(self):
+ self._obj = flashrom_handler.FlashromHandler()
+ self._obj.init(*self._args, **self._kargs)
+ self._obj.new_image()
+ self._loaded = True
+
+ def __getattr__(self, name):
+ if not self._loaded:
+ self._load()
+ return getattr(self._obj, name)
+
+ def reload(self):
+ """Reload the FlashromHandler class."""
+ self._loaded = False
+
+
+class FAFTClient(object):
+ """A class of FAFT client which aggregates some useful functions of SAFT.
+
+ This class can be exposed via a XMLRPC server such that its functions can
+ be accessed remotely. Method naming should fit the naming rule
+ '_[categories]_[method_name]' where categories contains system, ec, bios,
+ kernel, cgpt, tpm, updater, etc. Methods should be called by
+ 'FAFTClient.[categories].[method_name]', because _dispatch will rename
+ this name to '_[categories]_[method_name]'.
+
+ Attributes:
+ _chromeos_interface: An object to encapsulate OS services functions.
+ _bios_handler: An object to automate BIOS flashrom testing.
+ _ec_handler: An object to automate EC flashrom testing.
+ _ec_image: An object to automate EC image for autest.
+ _kernel_handler: An object to provide kernel related actions.
+ _log_file: Path of the log file.
+ _tpm_handler: An object to control TPM device.
+ _updater: An object to update firmware.
+ _temp_path: Path of a temp directory.
+ _keys_path: Path of a directory, keys/, in temp directory.
+ _work_path: Path of a directory, work/, in temp directory.
+ """
+ def __init__(self):
+ """Initialize the data attributes of this class."""
+ # TODO(waihong): Move the explicit object.init() methods to the
+ # objects' constructors (ChromeOSInterface, FlashromHandler,
+ # KernelHandler, and TpmHandler).
+ self._chromeos_interface = chromeos_interface.ChromeOSInterface(False)
+ # We keep the state of FAFT test in a permanent directory over reboots.
+ state_dir = '/var/tmp/faft'
+ self._log_file = os.path.join(state_dir, 'faft_client.log')
+ self._chromeos_interface.init(state_dir, log_file=self._log_file)
+ os.chdir(state_dir)
+
+ self._bios_handler = LazyFlashromHandlerProxy(
+ saft_flashrom_util,
+ self._chromeos_interface,
+ None,
+ '/usr/share/vboot/devkeys',
+ 'bios')
+
+ self._ec_handler = None
+ if not os.system("mosys ec info"):
+ self._ec_handler = LazyFlashromHandlerProxy(
+ saft_flashrom_util,
+ self._chromeos_interface,
+ 'ec_root_key.vpubk',
+ '/usr/share/vboot/devkeys',
+ 'ec')
+
+ self._ec_image = None
+
+ self._kernel_handler = kernel_handler.KernelHandler()
+ # TODO(waihong): The dev_key_path is a new argument. We do that in
+ # order not to break the old image and still be able to run.
+ try:
+ self._kernel_handler.init(self._chromeos_interface,
+ dev_key_path='/usr/share/vboot/devkeys',
+ internal_disk=True)
+ except TypeError:
+ # Copy the key to the current working directory.
+ shutil.copy('/usr/share/vboot/devkeys/kernel_data_key.vbprivk', '.')
+ self._kernel_handler.init(self._chromeos_interface,
+ internal_disk=True)
+
+ self._tpm_handler = tpm_handler.TpmHandler()
+ self._tpm_handler.init(self._chromeos_interface)
+
+ self._cgpt_state = cgpt_state.CgptState(
+ 'SHORT', self._chromeos_interface, self._system_get_root_dev())
+
+ self._updater = firmware_updater.FirmwareUpdater(self._chromeos_interface)
+
+ # Initialize temporary directory path
+ self._temp_path = '/var/tmp/faft/autest'
+ self._keys_path = os.path.join(self._temp_path, 'keys')
+ self._work_path = os.path.join(self._temp_path, 'work')
+
+ def _dispatch(self, method, params):
+ """This _dispatch method handles string conversion especially.
+
+ Since we turn off allow_dotted_names option. So any string conversion,
+ like str(FAFTClient.method), i.e. FAFTClient.method.__str__, failed
+ via XML RPC call.
+ """
+ is_str = method.endswith('.__str__')
+ if is_str:
+ method = method.rsplit('.', 1)[0]
+
+ categories = ('system', 'bios', 'ec', 'kernel',
+ 'tpm', 'cgpt', 'updater')
+ try:
+ if method.split('.', 1)[0] in categories:
+ func = getattr(self, '_%s_%s' % (method.split('.', 1)[0],
+ method.split('.', 1)[1]))
+ else:
+ func = getattr(self, method)
+ except AttributeError:
+ raise Exception('method "%s" is not supported' % method)
+
+ if is_str:
+ return str(func)
+ else:
+ self._chromeos_interface.log('Dispatching method %s with args %s' %
+ (str(func), str(params)))
+ return func(*params)
+
+ def _system_is_available(self):
+ """Function for polling the RPC server availability.
+
+ @return: Always True.
+ """
+ return True
+
+ def _system_dump_log(self, remove_log=False):
+ """Dump the log file.
+
+ @param remove_log: Remove the log file after dump.
+ @return: String of the log file content.
+ """
+ log = open(self._log_file).read()
+ if remove_log:
+ os.remove(self._log_file)
+ return log
+
+ def _system_run_shell_command(self, command):
+ """Run shell command.
+
+ @param command: A shell command to be run.
+ """
+ self._chromeos_interface.run_shell_command(command)
+
+ def _system_run_shell_command_get_output(self, command):
+ """Run shell command and get its console output.
+
+ @param command: A shell command to be run.
+ @return: A list of strings stripped of the newline characters.
+ """
+ return self._chromeos_interface.run_shell_command_get_output(command)
+
+ def _system_software_reboot(self):
+ """Request software reboot."""
+ self._chromeos_interface.run_shell_command('reboot')
+
+ def _system_get_platform_name(self):
+ """Get the platform name of the current system.
+
+ @return: A string of the platform name.
+ """
+ # 'mosys platform name' sometimes fails. Let's get the verbose output.
+ lines = self._chromeos_interface.run_shell_command_get_output(
+ '(mosys -vvv platform name 2>&1) || echo Failed')
+ if lines[-1].strip() == 'Failed':
+ raise Exception('Failed getting platform name: ' + '\n'.join(lines))
+ return lines[-1]
+
+ def _system_get_crossystem_value(self, key):
+ """Get crossystem value of the requested key.
+
+ @param key: A crossystem key.
+ @return: A string of the requested crossystem value.
+ """
+ return self._chromeos_interface.run_shell_command_get_output(
+ 'crossystem %s' % key)[0]
+
+ def _system_get_root_dev(self):
+ """Get the name of root device without partition number.
+
+ @return: A string of the root device without partition number.
+ """
+ return self._chromeos_interface.get_root_dev()
+
+ def _system_get_root_part(self):
+ """Get the name of root device with partition number.
+
+ @return: A string of the root device with partition number.
+ """
+ return self._chromeos_interface.get_root_part()
+
+ def _system_set_try_fw_b(self):
+ """Set 'Try Frimware B' flag in crossystem."""
+ self._chromeos_interface.cs.fwb_tries = 1
+
+ def _system_request_recovery_boot(self):
+ """Request running in recovery mode on the restart."""
+ self._chromeos_interface.cs.request_recovery()
+
+ def _system_get_dev_boot_usb(self):
+ """Get dev_boot_usb value which controls developer mode boot from USB.
+
+ @return: True if enable, False if disable.
+ """
+ return self._chromeos_interface.cs.dev_boot_usb == '1'
+
+ def _system_set_dev_boot_usb(self, value):
+ """Set dev_boot_usb value which controls developer mode boot from USB.
+
+ @param value: True to enable, False to disable.
+ """
+ self._chromeos_interface.cs.dev_boot_usb = 1 if value else 0
+
+ def _system_is_removable_device_boot(self):
+ """Check the current boot device is removable.
+
+ @return: True: if a removable device boots.
+ False: if a non-removable device boots.
+ """
+ root_part = self._chromeos_interface.get_root_part()
+ return self._chromeos_interface.is_removable_device(root_part)
+
+ def _system_create_temp_dir(self, prefix='backup_'):
+ """Create a temporary directory and return the path."""
+ return tempfile.mkdtemp(prefix=prefix)
+
+ def _bios_reload(self):
+ """Reload the firmware image that may be changed."""
+ self._bios_handler.reload()
+
+ def _bios_get_gbb_flags(self):
+ """Get the GBB flags.
+
+ @return: An integer of the GBB flags.
+ """
+ return self._bios_handler.get_gbb_flags()
+
+ def _bios_get_preamble_flags(self, section):
+ """Get the preamble flags of a firmware section.
+
+ @param section: A firmware section, either 'a' or 'b'.
+ @return: An integer of the preamble flags.
+ """
+ return self._bios_handler.get_section_flags(section)
+
+ def _bios_set_preamble_flags(self, section, flags):
+ """Set the preamble flags of a firmware section.
+
+ @param section: A firmware section, either 'a' or 'b'.
+ @param flags: An integer of preamble flags.
+ """
+ version = self._bios_get_version(section)
+ self._bios_handler.set_section_version(section, version, flags,
+ write_through=True)
+
+ def _bios_get_body_sha(self, section):
+ """Get SHA1 hash of BIOS RW firmware section.
+
+ @param section: A firmware section, either 'a' or 'b'.
+ @param flags: An integer of preamble flags.
+ """
+ return self._bios_handler.get_section_sha(section)
+
+ def _bios_get_sig_sha(self, section):
+ """Get SHA1 hash of firmware vblock in section."""
+ return self._bios_handler.get_section_sig_sha(section)
+
+ @allow_multiple_section_input
+ def _bios_corrupt_sig(self, section):
+ """Corrupt the requested firmware section signature.
+
+ @param section: A firmware section, either 'a' or 'b'.
+ """
+ self._bios_handler.corrupt_firmware(section)
+
+ @allow_multiple_section_input
+ def _bios_restore_sig(self, section):
+ """Restore the previously corrupted firmware section signature.
+
+ @param section: A firmware section, either 'a' or 'b'.
+ """
+ self._bios_handler.restore_firmware(section)
+
+ @allow_multiple_section_input
+ def _bios_corrupt_body(self, section):
+ """Corrupt the requested firmware section body.
+
+ @param section: A firmware section, either 'a' or 'b'.
+ """
+ self._bios_handler.corrupt_firmware_body(section)
+
+ @allow_multiple_section_input
+ def _bios_restore_body(self, section):
+ """Restore the previously corrupted firmware section body.
+
+ @param section: A firmware section, either 'a' or 'b'.
+ """
+ self._bios_handler.restore_firmware_body(section)
+
+ def __bios_modify_version(self, section, delta):
+ """Modify firmware version for the requested section, by adding delta.
+
+ The passed in delta, a positive or a negative number, is added to the
+ original firmware version.
+ """
+ original_version = self._bios_get_version(section)
+ new_version = original_version + delta
+ flags = self._bios_handler.get_section_flags(section)
+ self._chromeos_interface.log(
+ 'Setting firmware section %s version from %d to %d' % (
+ section, original_version, new_version))
+ self._bios_handler.set_section_version(section, new_version, flags,
+ write_through=True)
+
+ @allow_multiple_section_input
+ def _bios_move_version_backward(self, section):
+ """Decrement firmware version for the requested section."""
+ self.__bios_modify_version(section, -1)
+
+ @allow_multiple_section_input
+ def _bios_move_version_forward(self, section):
+ """Increase firmware version for the requested section."""
+ self.__bios_modify_version(section, 1)
+
+ def _bios_get_version(self, section):
+ """Retrieve firmware version of a section."""
+ return self._bios_handler.get_section_version(section)
+
+ def _bios_get_datakey_version(self, section):
+ """Return firmware data key version."""
+ return self._bios_handler.get_section_datakey_version(section)
+
+ def _bios_get_kernel_subkey_version(self, section):
+ """Return kernel subkey version."""
+ return self._bios_handler.get_section_kernel_subkey_version(section)
+
+ def _bios_setup_EC_image(self, ec_path):
+ """Setup the new EC image for later update.
+
+ @param ec_path: The path of the EC image to be updated.
+ """
+ self._ec_image = flashrom_handler.FlashromHandler()
+ self._ec_image.init(saft_flashrom_util,
+ self._chromeos_interface,
+ 'ec_root_key.vpubk',
+ '/usr/share/vboot/devkeys',
+ 'ec')
+ self._ec_image.new_image(ec_path)
+
+ def _bios_get_EC_image_sha(self):
+ """Get SHA1 hash of RW firmware section of the EC autest image."""
+ return self._ec_image.get_section_sha('rw')
+
+ def _bios_update_EC_from_image(self, section, flags):
+ """Update EC via software sync design.
+
+ It copys the RW section from the EC image, which is loaded by calling
+ bios_setup_EC_image(), to the EC area of the specified RW section on the
+ current AP firmware.
+
+ @param section: A firmware section on current BIOS, either 'a' or 'b'.
+ @param flags: An integer of preamble flags.
+ """
+ blob = self._ec_image.get_section_body('rw')
+ self._bios_handler.set_section_ecbin(section, blob,
+ write_through=True)
+ self._bios_set_preamble_flags(section, flags)
+
+ def _bios_dump_whole(self, bios_path):
+ """Dump the current BIOS firmware to a file, specified by bios_path.
+
+ @param bios_path: The path of the BIOS image to be written.
+ """
+ self._bios_handler.dump_whole(bios_path)
+
+ def _bios_dump_rw(self, dir_path):
+ """Dump the current BIOS firmware RW to dir_path.
+
+ VBOOTA, VBOOTB, FVMAIN, FVMAINB need to be dumped.
+
+ @param dir_path: The path of directory which contains files to be
+ written.
+ """
+ if not os.path.isdir(dir_path):
+ raise Exception("%s doesn't exist" % dir_path)
+
+ VBOOTA_blob = self._bios_handler.get_section_sig('a')
+ VBOOTB_blob = self._bios_handler.get_section_sig('b')
+ FVMAIN_blob = self._bios_handler.get_section_body('a')
+ FVMAINB_blob = self._bios_handler.get_section_body('b')
+
+ open(os.path.join(dir_path, 'VBOOTA'), 'w').write(VBOOTA_blob)
+ open(os.path.join(dir_path, 'VBOOTB'), 'w').write(VBOOTB_blob)
+ open(os.path.join(dir_path, 'FVMAIN'), 'w').write(FVMAIN_blob)
+ open(os.path.join(dir_path, 'FVMAINB'), 'w').write(FVMAINB_blob)
+
+ def _bios_write_whole(self, bios_path):
+ """Write the firmware from bios_path to the current system.
+
+ @param bios_path: The path of the source BIOS image.
+ """
+ self._bios_handler.new_image(bios_path)
+ self._bios_handler.write_whole()
+
+ def _bios_write_rw(self, dir_path):
+ """Write the firmware RW from dir_path to the current system.
+
+ VBOOTA, VBOOTB, FVMAIN, FVMAINB need to be written.
+
+ @param dir_path: The path of directory which contains the source files.
+ """
+ if not os.path.exists(os.path.join(dir_path, 'VBOOTA')) or \
+ not os.path.exists(os.path.join(dir_path, 'VBOOTB')) or \
+ not os.path.exists(os.path.join(dir_path, 'FVMAIN')) or \
+ not os.path.exists(os.path.join(dir_path, 'FVMAINB')):
+ raise Exception("Source firmware file(s) doesn't exist.")
+
+ VBOOTA_blob = open(os.path.join(dir_path, 'VBOOTA'), 'rb').read()
+ VBOOTB_blob = open(os.path.join(dir_path, 'VBOOTB'), 'rb').read()
+ FVMAIN_blob = open(os.path.join(dir_path, 'FVMAIN'), 'rb').read()
+ FVMAINB_blob = open(os.path.join(dir_path, 'FVMAINB'), 'rb').read()
+
+ self._bios_handler.set_section_sig('a', VBOOTA_blob,
+ write_through=True)
+ self._bios_handler.set_section_sig('b', VBOOTB_blob,
+ write_through=True)
+ self._bios_handler.set_section_body('a', FVMAIN_blob,
+ write_through=True)
+ self._bios_handler.set_section_body('b', FVMAINB_blob,
+ write_through=True)
+
+ def _ec_get_version(self):
+ """Get EC version via mosys.
+
+ @return: A string of the EC version.
+ """
+ return self._chromeos_interface.run_shell_command_get_output(
+ 'mosys ec info | sed "s/.*| //"')[0]
+
+ def _ec_get_firmware_sha(self):
+ """Get SHA1 hash of EC RW firmware section."""
+ return self._ec_handler.get_section_sha('rw')
+
+ @allow_multiple_section_input
+ def _ec_corrupt_sig(self, section):
+ """Corrupt the requested EC section signature.
+
+ @param section: A EC section, either 'a' or 'b'.
+ """
+ self._ec_handler.corrupt_firmware(section, corrupt_all=True)
+
+ @allow_multiple_section_input
+ def _ec_restore_sig(self, section):
+ """Restore the previously corrupted EC section signature.
+
+ @param section: An EC section, either 'a' or 'b'.
+ """
+ self._ec_handler.restore_firmware(section, restore_all=True)
+
+ @allow_multiple_section_input
+ def _ec_corrupt_body(self, section):
+ """Corrupt the requested EC section body.
+
+ @param section: An EC section, either 'a' or 'b'.
+ """
+ self._ec_handler.corrupt_firmware_body(section, corrupt_all=True)
+
+ @allow_multiple_section_input
+ def _ec_restore_body(self, section):
+ """Restore the previously corrupted EC section body.
+
+ @param section: An EC section, either 'a' or 'b'.
+ """
+ self._ec_handler.restore_firmware_body(section, restore_all=True)
+
+ def _ec_dump_firmware(self, ec_path):
+ """Dump the current EC firmware to a file, specified by ec_path.
+
+ @param ec_path: The path of the EC image to be written.
+ """
+ self._ec_handler.dump_whole(ec_path)
+
+ def _ec_set_write_protect(self, enable):
+ """Enable write protect of the EC flash chip.
+
+ @param enable: True if activating EC write protect. Otherwise, False.
+ """
+ if enable:
+ self._ec_handler.enable_write_protect()
+ else:
+ self._ec_handler.disable_write_protect()
+
+ @allow_multiple_section_input
+ def _kernel_corrupt_sig(self, section):
+ """Corrupt the requested kernel section.
+
+ @param section: A kernel section, either 'a' or 'b'.
+ """
+ self._kernel_handler.corrupt_kernel(section)
+
+ @allow_multiple_section_input
+ def _kernel_restore_sig(self, section):
+ """Restore the requested kernel section (previously corrupted).
+
+ @param section: A kernel section, either 'a' or 'b'.
+ """
+ self._kernel_handler.restore_kernel(section)
+
+ def __kernel_modify_version(self, section, delta):
+ """Modify kernel version for the requested section, by adding delta.
+
+ The passed in delta, a positive or a negative number, is added to the
+ original kernel version.
+ """
+ original_version = self._kernel_handler.get_version(section)
+ new_version = original_version + delta
+ self._chromeos_interface.log(
+ 'Setting kernel section %s version from %d to %d' % (
+ section, original_version, new_version))
+ self._kernel_handler.set_version(section, new_version)
+
+ @allow_multiple_section_input
+ def _kernel_move_version_backward(self, section):
+ """Decrement kernel version for the requested section."""
+ self.__kernel_modify_version(section, -1)
+
+ @allow_multiple_section_input
+ def _kernel_move_version_forward(self, section):
+ """Increase kernel version for the requested section."""
+ self.__kernel_modify_version(section, 1)
+
+ def _kernel_get_version(self, section):
+ """Return kernel version."""
+ return self._kernel_handler.get_version(section)
+
+ def _kernel_get_datakey_version(self, section):
+ """Return kernel datakey version."""
+ return self._kernel_handler.get_datakey_version(section)
+
+ def _kernel_diff_a_b(self):
+ """Compare kernel A with B.
+
+ @return: True: if kernel A is different with B.
+ False: if kernel A is the same as B.
+ """
+ rootdev = self._chromeos_interface.get_root_dev()
+ kernel_a = self._chromeos_interface.join_part(rootdev, '3')
+ kernel_b = self._chromeos_interface.join_part(rootdev, '5')
+
+ # The signature (some kind of hash) for the kernel body is stored in
+ # the beginning. So compare the first 64KB (including header, preamble,
+ # and signature) should be enough to check them identical.
+ header_a = self._chromeos_interface.read_partition(kernel_a, 0x10000)
+ header_b = self._chromeos_interface.read_partition(kernel_b, 0x10000)
+
+ return header_a != header_b
+
+ def _kernel_resign_with_keys(self, section, key_path=None):
+ """Resign kernel with temporary key."""
+ self._kernel_handler.resign_kernel(section, key_path)
+
+ def _tpm_get_firmware_version(self):
+ """Retrieve tpm firmware body version."""
+ return self._tpm_handler.get_fw_version()
+
+ def _tpm_get_firmware_datakey_version(self):
+ """Retrieve tpm firmware data key version."""
+ return self._tpm_handler.get_fw_body_version()
+
+ def _cgpt_run_test_loop(self):
+ """Run the CgptState test loop. The tst logic is handled in the client.
+
+ @return: 0: there are more cgpt tests to execute.
+ 1: no more CgptState test, finished.
+ """
+ return self._cgpt_state.test_loop()
+
+ def _cgpt_set_test_step(self, step):
+ """Set the CgptState test step.
+
+ @param step: A test step number.
+ """
+ self._cgpt_state.set_step(step)
+
+ def _cgpt_get_test_step(self):
+ """Get the CgptState test step.
+
+ @return: A test step number.
+ """
+ return self._cgpt_state.get_step()
+
+ def _updater_setup(self, shellball=None):
+ """Setup the updater.
+
+ @param shellball: Path of provided shellball. Use default shellball
+ if None,
+ """
+ self._updater.setup(self._chromeos_interface, shellball)
+
+ def _updater_cleanup(self):
+ self._updater.cleanup_temp_dir()
+
+ def _updater_get_fwid(self):
+ """Retrieve shellball's fwid.
+
+ This method should be called after updater_setup.
+
+ @return: Shellball's fwid.
+ """
+ return self._updater.retrieve_fwid()
+
+ def _updater_resign_firmware(self, version):
+ """Resign firmware with version.
+
+ @param version: new version number.
+ """
+ self._updater.resign_firmware(version)
+
+ def _updater_repack_shellball(self, append):
+ """Repack shellball with new fwid.
+
+ @param append: use for new fwid naming.
+ """
+ self._updater.repack_shellball(append)
+
+ def _updater_run_autoupdate(self, append):
+ """Run chromeos-firmwareupdate with autoupdate mode."""
+ options = ['--noupdate_ec', '--nocheck_rw_compatible']
+ self._updater.run_firmwareupdate(mode='autoupdate',
+ updater_append=append,
+ options=options)
+
+ def _updater_run_factory_install(self):
+ """Run chromeos-firmwareupdate with factory_install mode."""
+ options = ['--noupdate_ec']
+ self._updater.run_firmwareupdate(mode='factory_install',
+ options=options)
+
+ def _updater_run_bootok(self, append):
+ """Run chromeos-firmwareupdate with bootok mode."""
+ self._updater.run_firmwareupdate(mode='bootok',
+ updater_append=append)
+
+ def _updater_run_recovery(self):
+ """Run chromeos-firmwareupdate with recovery mode."""
+ options = ['--noupdate_ec', '--nocheck_rw_compatible']
+ self._updater.run_firmwareupdate(mode='recovery',
+ options=options)
+
+ def _updater_get_temp_path(self):
+ """Get updater's temp directory path."""
+ return self._updater.get_temp_path()
+
+ def _updater_get_keys_path(self):
+ """Get updater's keys directory path."""
+ return self._updater.get_keys_path()
+
+ def _updater_get_work_path(self):
+ """Get updater's work directory path."""
+ return self._updater.get_work_path()
+
+ def cleanup(self):
+ """Cleanup for the RPC server. Currently nothing."""
+ pass
+
+
+def main():
+ """The Main program, to run the XMLRPC server."""
+ parser = OptionParser(usage='Usage: %prog [options]')
+ parser.add_option('--port', type='int', dest='port', default=9990,
+ help='port number of XMLRPC server')
+ (options, _) = parser.parse_args()
+
+ faft_client = FAFTClient()
+
+ # Launch the XMLRPC server to provide FAFTClient commands.
+ server = SimpleXMLRPCServer(('localhost', options.port), allow_none=True,
+ logRequests=True)
+ server.register_introspection_functions()
+ server.register_instance(faft_client)
+ print 'XMLRPC Server: Serving FAFTClient on port %s' % options.port
+ server.serve_forever()
+
+
+if __name__ == '__main__':
+ main()