Home | History | Annotate | Download | only in faft
      1 # Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
      2 # Use of this source code is governed by a BSD-style license that can be
      3 # found in the LICENSE file.
      4 
      5 """Code to provide functions for FAFT tests.
      6 
      7 These can be exposed via a xmlrpci server running on the DUT.
      8 """
      9 
     10 import functools, os, tempfile
     11 import traceback
     12 
     13 from autotest_lib.client.cros.faft.utils import (cgpt_handler,
     14                                                  common,
     15                                                  os_interface,
     16                                                  firmware_check_keys,
     17                                                  firmware_updater,
     18                                                  flashrom_handler,
     19                                                  kernel_handler,
     20                                                  rootfs_handler,
     21                                                  saft_flashrom_util,
     22                                                  tpm_handler,
     23                                                 )
     24 
     25 
     26 def allow_multiple_section_input(image_operator):
     27     """Decorate a method to support multiple sections.
     28 
     29     @param image_operator: Method accepting one section as its argument.
     30     """
     31     @functools.wraps(image_operator)
     32     def wrapper(self, section, *args, **dargs):
     33         """Wrapper method to support multiple sections.
     34 
     35         @param section: A list of sections of just a section.
     36         """
     37         if type(section) in (tuple, list):
     38             for sec in section:
     39                 image_operator(self, sec, *args, **dargs)
     40         else:
     41             image_operator(self, section, *args, **dargs)
     42     return wrapper
     43 
     44 
     45 class RPCFunctions(object):
     46     """A class which aggregates some useful functions for firmware testing.
     47 
     48     This class can be exposed via a XMLRPC server such that its functions can
     49     be accessed remotely. Method naming should fit the naming rule
     50     '_[categories]_[method_name]' where categories contains system, ec, bios,
     51     kernel, cgpt, tpm, updater, etc. Methods should be called by
     52     'FAFTClient.[categories].[method_name]', because _dispatch will rename
     53     this name to '_[categories]_[method_name]'.
     54 
     55     Attributes:
     56         _os_if: An object to encapsulate OS services functions.
     57         _bios_handler: An object to automate BIOS flashrom testing.
     58         _ec_handler: An object to automate EC flashrom testing.
     59         _kernel_handler: An object to provide kernel related actions.
     60         _log_file: Path of the log file.
     61         _tpm_handler: An object to control TPM device.
     62         _updater: An object to update firmware.
     63         _temp_path: Path of a temp directory.
     64         _keys_path: Path of a directory, keys/, in temp directory.
     65         _work_path: Path of a directory, work/, in temp directory.
     66     """
     67 
     68     def __init__(self):
     69         """Initialize the data attributes of this class."""
     70         # TODO(waihong): Move the explicit object.init() methods to the
     71         # objects' constructors (OSInterface, FlashromHandler,
     72         # KernelHandler, and TpmHandler).
     73         self._os_if = os_interface.OSInterface()
     74         # We keep the state of FAFT test in a permanent directory over reboots.
     75         state_dir = '/var/tmp/faft'
     76         self._log_file = os.path.join(state_dir, 'faft_client.log')
     77         self._os_if.init(state_dir, log_file=self._log_file)
     78         os.chdir(state_dir)
     79 
     80         self._bios_handler = common.LazyInitHandlerProxy(
     81                 flashrom_handler.FlashromHandler,
     82                 saft_flashrom_util,
     83                 self._os_if,
     84                 None,
     85                 '/usr/share/vboot/devkeys',
     86                 'bios')
     87 
     88         self._ec_handler = None
     89         if self._os_if.run_shell_command_get_status('mosys ec info') == 0:
     90             self._ec_handler = common.LazyInitHandlerProxy(
     91                     flashrom_handler.FlashromHandler,
     92                     saft_flashrom_util,
     93                     self._os_if,
     94                     'ec_root_key.vpubk',
     95                     '/usr/share/vboot/devkeys',
     96                     'ec')
     97         else:
     98             self._os_if.log('No EC is reported by mosys.')
     99 
    100         self._kernel_handler = kernel_handler.KernelHandler()
    101         self._kernel_handler.init(self._os_if,
    102                                   dev_key_path='/usr/share/vboot/devkeys',
    103                                   internal_disk=True)
    104 
    105         self._tpm_handler = common.LazyInitHandlerProxy(
    106                 tpm_handler.TpmHandler,
    107                 self._os_if)
    108 
    109         self._cgpt_handler = cgpt_handler.CgptHandler(self._os_if)
    110 
    111         self._rootfs_handler = rootfs_handler.RootfsHandler()
    112         self._rootfs_handler.init(self._os_if)
    113 
    114         self._updater = firmware_updater.FirmwareUpdater(self._os_if)
    115         self._check_keys = firmware_check_keys.firmwareCheckKeys()
    116 
    117         # 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 
    122     def _dispatch(self, method, params):
    123         """This _dispatch method handles string conversion especially.
    124 
    125         Since we turn off allow_dotted_names option. So any string conversion,
    126         like str(FAFTClient.method), i.e. FAFTClient.method.__str__, failed
    127         via XML RPC call.
    128         """
    129         is_str = method.endswith('.__str__')
    130         if is_str:
    131             method = method.rsplit('.', 1)[0]
    132 
    133         categories = ('system', 'host', 'bios', 'ec', 'kernel',
    134                       'tpm', 'cgpt', 'updater', 'rootfs')
    135         try:
    136             if method.split('.', 1)[0] in categories:
    137                 func = getattr(self, '_%s_%s' % (method.split('.', 1)[0],
    138                                                  method.split('.', 1)[1]))
    139             else:
    140                 func = getattr(self, method)
    141         except AttributeError:
    142             raise Exception('method "%s" is not supported' % method)
    143 
    144         if is_str:
    145             return str(func)
    146         else:
    147             try:
    148                 self._os_if.log('Dispatching method %s with args %r' %
    149                     (func.__name__, params))
    150                 return func(*params)
    151             except:
    152                 self._os_if.log(
    153                     'Dispatching of method %s failed: %s' %
    154                     (func.__name__, traceback.format_exc()))
    155                 raise
    156 
    157     def _system_is_available(self):
    158         """Function for polling the RPC server availability.
    159 
    160         @return: Always True.
    161         """
    162         return True
    163 
    164     def _system_has_host(self):
    165         """Return True if a host is connected to DUT."""
    166         return self._os_if.has_host()
    167 
    168     def _system_wait_for_client(self, timeout):
    169         """Wait for the client to come back online.
    170 
    171         @param timeout: Time in seconds to wait for the client SSH daemon to
    172                         come up.
    173         @return: True if succeed; otherwise False.
    174         """
    175         return self._os_if.wait_for_device(timeout)
    176 
    177     def _system_wait_for_client_offline(self, timeout):
    178         """Wait for the client to come offline.
    179 
    180         @param timeout: Time in seconds to wait the client to come offline.
    181         @return: True if succeed; otherwise False.
    182         """
    183         return self._os_if.wait_for_no_device(timeout)
    184 
    185     def _system_dump_log(self, remove_log=False):
    186         """Dump the log file.
    187 
    188         @param remove_log: Remove the log file after dump.
    189         @return: String of the log file content.
    190         """
    191         log = open(self._log_file).read()
    192         if remove_log:
    193             os.remove(self._log_file)
    194         return log
    195 
    196     def _system_run_shell_command(self, command):
    197         """Run shell command.
    198 
    199         @param command: A shell command to be run.
    200         """
    201         self._os_if.run_shell_command(command)
    202 
    203     def _system_run_shell_command_get_output(self, command):
    204         """Run shell command and get its console output.
    205 
    206         @param command: A shell command to be run.
    207         @return: A list of strings stripped of the newline characters.
    208         """
    209         return self._os_if.run_shell_command_get_output(command)
    210 
    211     def _host_run_shell_command(self, command):
    212         """Run shell command on the host.
    213 
    214         @param command: A shell command to be run.
    215         """
    216         self._os_if.run_host_shell_command(command)
    217 
    218     def _host_run_shell_command_get_output(self, command):
    219         """Run shell command and get its console output on the host.
    220 
    221         @param command: A shell command to be run.
    222         @return: A list of strings stripped of the newline characters.
    223         """
    224         return self._os_if.run_host_shell_command_get_output(command)
    225 
    226     def _host_run_nonblock_shell_command(self, command):
    227         """Run non-blocking shell command.
    228 
    229         @param command: A shell command to be run.
    230         @return: none
    231         """
    232         return self._os_if.run_host_shell_command(command, False)
    233 
    234     def _system_software_reboot(self):
    235         """Request software reboot."""
    236         self._os_if.run_shell_command('reboot')
    237 
    238     def _system_get_platform_name(self):
    239         """Get the platform name of the current system.
    240 
    241         @return: A string of the platform name.
    242         """
    243         # 'mosys platform name' sometimes fails. Let's get the verbose output.
    244         lines = self._os_if.run_shell_command_get_output(
    245                 '(mosys -vvv platform name 2>&1) || echo Failed')
    246         if lines[-1].strip() == 'Failed':
    247             raise Exception('Failed getting platform name: ' + '\n'.join(lines))
    248         return lines[-1]
    249 
    250     def _system_dev_tpm_present(self):
    251         """Check if /dev/tpm0 is present.
    252 
    253         @return: Boolean true or false.
    254         """
    255         return os.path.exists('/dev/tpm0')
    256 
    257     def _system_get_crossystem_value(self, key):
    258         """Get crossystem value of the requested key.
    259 
    260         @param key: A crossystem key.
    261         @return: A string of the requested crossystem value.
    262         """
    263         return self._os_if.run_shell_command_get_output(
    264                 'crossystem %s' % key)[0]
    265 
    266     def _system_get_root_dev(self):
    267         """Get the name of root device without partition number.
    268 
    269         @return: A string of the root device without partition number.
    270         """
    271         return self._os_if.get_root_dev()
    272 
    273     def _system_get_root_part(self):
    274         """Get the name of root device with partition number.
    275 
    276         @return: A string of the root device with partition number.
    277         """
    278         return self._os_if.get_root_part()
    279 
    280     def _system_set_try_fw_b(self, count=1):
    281         """Set 'Try Frimware B' flag in crossystem.
    282 
    283         @param count: # times to try booting into FW B
    284         """
    285         self._os_if.cs.fwb_tries = count
    286 
    287     def _system_set_fw_try_next(self, next, count=0):
    288         """Set fw_try_next to A or B.
    289 
    290         @param next: Next FW to reboot to (A or B)
    291         @param count: # of times to try booting into FW <next>
    292         """
    293         self._os_if.cs.fw_try_next = next
    294         if count:
    295             self._os_if.cs.fw_try_count = count
    296 
    297     def _system_get_fw_vboot2(self):
    298         """Get fw_vboot2."""
    299         try:
    300             return self._os_if.cs.fw_vboot2 == '1'
    301         except os_interface.OSInterfaceError:
    302             return False
    303 
    304     def _system_request_recovery_boot(self):
    305         """Request running in recovery mode on the restart."""
    306         self._os_if.cs.request_recovery()
    307 
    308     def _system_get_dev_boot_usb(self):
    309         """Get dev_boot_usb value which controls developer mode boot from USB.
    310 
    311         @return: True if enable, False if disable.
    312         """
    313         return self._os_if.cs.dev_boot_usb == '1'
    314 
    315     def _system_set_dev_boot_usb(self, value):
    316         """Set dev_boot_usb value which controls developer mode boot from USB.
    317 
    318         @param value: True to enable, False to disable.
    319         """
    320         self._os_if.cs.dev_boot_usb = 1 if value else 0
    321 
    322     def _system_is_removable_device_boot(self):
    323         """Check the current boot device is removable.
    324 
    325         @return: True: if a removable device boots.
    326                  False: if a non-removable device boots.
    327         """
    328         root_part = self._os_if.get_root_part()
    329         return self._os_if.is_removable_device(root_part)
    330 
    331     def _system_get_internal_device(self):
    332         """Get the internal disk by given the current disk."""
    333         root_part = self._os_if.get_root_part()
    334         return self._os_if.get_internal_disk(root_part)
    335 
    336     def _system_create_temp_dir(self, prefix='backup_'):
    337         """Create a temporary directory and return the path."""
    338         return tempfile.mkdtemp(prefix=prefix)
    339 
    340     def _system_remove_file(self, file_path):
    341         """Remove the file."""
    342         return self._os_if.remove_file(file_path)
    343 
    344     def _system_remove_dir(self, dir_path):
    345         """Remove the directory."""
    346         return self._os_if.remove_dir(dir_path)
    347 
    348     def _bios_reload(self):
    349         """Reload the firmware image that may be changed."""
    350         self._bios_handler.reload()
    351 
    352     def _bios_get_gbb_flags(self):
    353         """Get the GBB flags.
    354 
    355         @return: An integer of the GBB flags.
    356         """
    357         return self._bios_handler.get_gbb_flags()
    358 
    359     def _bios_set_gbb_flags(self, flags):
    360         """Set the GBB flags.
    361 
    362         @param flags: An integer of the GBB flags.
    363         """
    364         self._bios_handler.set_gbb_flags(flags, write_through=True)
    365 
    366     def _bios_get_preamble_flags(self, section):
    367         """Get the preamble flags of a firmware section.
    368 
    369         @param section: A firmware section, either 'a' or 'b'.
    370         @return: An integer of the preamble flags.
    371         """
    372         return self._bios_handler.get_section_flags(section)
    373 
    374     def _bios_set_preamble_flags(self, section, flags):
    375         """Set the preamble flags of a firmware section.
    376 
    377         @param section: A firmware section, either 'a' or 'b'.
    378         @param flags: An integer of preamble flags.
    379         """
    380         version = self._bios_get_version(section)
    381         self._bios_handler.set_section_version(section, version, flags,
    382                                                write_through=True)
    383 
    384     def _bios_get_body_sha(self, section):
    385         """Get SHA1 hash of BIOS RW firmware section.
    386 
    387         @param section: A firmware section, either 'a' or 'b'.
    388         @param flags: An integer of preamble flags.
    389         """
    390         return self._bios_handler.get_section_sha(section)
    391 
    392     def _bios_get_sig_sha(self, section):
    393         """Get SHA1 hash of firmware vblock in section."""
    394         return self._bios_handler.get_section_sig_sha(section)
    395 
    396     @allow_multiple_section_input
    397     def _bios_corrupt_sig(self, section):
    398         """Corrupt the requested firmware section signature.
    399 
    400         @param section: A firmware section, either 'a' or 'b'.
    401         """
    402         self._bios_handler.corrupt_firmware(section)
    403 
    404     @allow_multiple_section_input
    405     def _bios_restore_sig(self, section):
    406         """Restore the previously corrupted firmware section signature.
    407 
    408         @param section: A firmware section, either 'a' or 'b'.
    409         """
    410         self._bios_handler.restore_firmware(section)
    411 
    412     @allow_multiple_section_input
    413     def _bios_corrupt_body(self, section, corrupt_all=False):
    414         """Corrupt the requested firmware section body.
    415 
    416         @param section: A firmware section, either 'a' or 'b'.
    417         """
    418         self._bios_handler.corrupt_firmware_body(section, corrupt_all)
    419 
    420     @allow_multiple_section_input
    421     def _bios_restore_body(self, section):
    422         """Restore the previously corrupted firmware section body.
    423 
    424         @param section: A firmware section, either 'a' or 'b'.
    425         """
    426         self._bios_handler.restore_firmware_body(section)
    427 
    428     def __bios_modify_version(self, section, delta):
    429         """Modify firmware version for the requested section, by adding delta.
    430 
    431         The passed in delta, a positive or a negative number, is added to the
    432         original firmware version.
    433         """
    434         original_version = self._bios_get_version(section)
    435         new_version = original_version + delta
    436         flags = self._bios_handler.get_section_flags(section)
    437         self._os_if.log(
    438                 'Setting firmware section %s version from %d to %d' % (
    439                 section, original_version, new_version))
    440         self._bios_handler.set_section_version(section, new_version, flags,
    441                                                write_through=True)
    442 
    443     @allow_multiple_section_input
    444     def _bios_move_version_backward(self, section):
    445         """Decrement firmware version for the requested section."""
    446         self.__bios_modify_version(section, -1)
    447 
    448     @allow_multiple_section_input
    449     def _bios_move_version_forward(self, section):
    450         """Increase firmware version for the requested section."""
    451         self.__bios_modify_version(section, 1)
    452 
    453     def _bios_get_version(self, section):
    454         """Retrieve firmware version of a section."""
    455         return self._bios_handler.get_section_version(section)
    456 
    457     def _bios_get_datakey_version(self, section):
    458         """Return firmware data key version."""
    459         return self._bios_handler.get_section_datakey_version(section)
    460 
    461     def _bios_get_kernel_subkey_version(self, section):
    462         """Return kernel subkey version."""
    463         return self._bios_handler.get_section_kernel_subkey_version(section)
    464 
    465     def _bios_dump_whole(self, bios_path):
    466         """Dump the current BIOS firmware to a file, specified by bios_path.
    467 
    468         @param bios_path: The path of the BIOS image to be written.
    469         """
    470         self._bios_handler.dump_whole(bios_path)
    471 
    472     def _bios_write_whole(self, bios_path):
    473         """Write the firmware from bios_path to the current system.
    474 
    475         @param bios_path: The path of the source BIOS image.
    476         """
    477         self._bios_handler.new_image(bios_path)
    478         self._bios_handler.write_whole()
    479 
    480     def _ec_get_version(self):
    481         """Get EC version via mosys.
    482 
    483         @return: A string of the EC version.
    484         """
    485         return self._os_if.run_shell_command_get_output(
    486                 'mosys ec info | sed "s/.*| //"')[0]
    487 
    488     def _ec_get_firmware_sha(self):
    489         """Get SHA1 hash of EC RW firmware section."""
    490         return self._ec_handler.get_section_sha('rw')
    491 
    492     def _ec_get_active_hash(self):
    493         """Get hash of active EC RW firmware."""
    494         return self._os_if.run_shell_command_get_output(
    495                 'ectool echash | grep hash: | sed "s/hash:\s\+//"')[0]
    496 
    497     def _ec_dump_whole(self, ec_path):
    498         """Dump the current EC firmware to a file, specified by ec_path.
    499 
    500         @param ec_path: The path of the EC image to be written.
    501         """
    502         self._ec_handler.dump_whole(ec_path)
    503 
    504     def _ec_write_whole(self, ec_path):
    505         """Write the firmware from ec_path to the current system.
    506 
    507         @param ec_path: The path of the source EC image.
    508         """
    509         self._ec_handler.new_image(ec_path)
    510         self._ec_handler.write_whole()
    511 
    512     @allow_multiple_section_input
    513     def _ec_corrupt_sig(self, section):
    514         """Corrupt the requested EC section signature.
    515 
    516         @param section: A EC section, either 'a' or 'b'.
    517         """
    518         self._ec_handler.corrupt_firmware(section, corrupt_all=True)
    519 
    520     @allow_multiple_section_input
    521     def _ec_restore_sig(self, section):
    522         """Restore the previously corrupted EC section signature.
    523 
    524         @param section: An EC section, either 'a' or 'b'.
    525         """
    526         self._ec_handler.restore_firmware(section, restore_all=True)
    527 
    528     @allow_multiple_section_input
    529     def _ec_corrupt_body(self, section):
    530         """Corrupt the requested EC section body.
    531 
    532         @param section: An EC section, either 'a' or 'b'.
    533         """
    534         self._ec_handler.corrupt_firmware_body(section, corrupt_all=True)
    535 
    536     @allow_multiple_section_input
    537     def _ec_restore_body(self, section):
    538         """Restore the previously corrupted EC section body.
    539 
    540         @param section: An EC section, either 'a' or 'b'.
    541         """
    542         self._ec_handler.restore_firmware_body(section, restore_all=True)
    543 
    544     def _ec_dump_firmware(self, ec_path):
    545         """Dump the current EC firmware to a file, specified by ec_path.
    546 
    547         @param ec_path: The path of the EC image to be written.
    548         """
    549         self._ec_handler.dump_whole(ec_path)
    550 
    551     def _ec_set_write_protect(self, enable):
    552         """Enable write protect of the EC flash chip.
    553 
    554         @param enable: True if activating EC write protect. Otherwise, False.
    555         """
    556         if enable:
    557             self._ec_handler.enable_write_protect()
    558         else:
    559             self._ec_handler.disable_write_protect()
    560 
    561     def _ec_is_efs(self):
    562         """Return True if the EC supports EFS."""
    563         return self._ec_handler.has_section_body('rw_b')
    564 
    565     def _ec_copy_rw(self, from_section, to_section):
    566         """Copy EC RW from from_section to to_section."""
    567         self._ec_handler.copy_from_to(from_section, to_section)
    568 
    569     def _ec_reboot_to_switch_slot(self):
    570         """Reboot EC to switch the active RW slot."""
    571         self._os_if.run_shell_command(
    572                 'ectool reboot_ec cold switch-slot')
    573 
    574     @allow_multiple_section_input
    575     def _kernel_corrupt_sig(self, section):
    576         """Corrupt the requested kernel section.
    577 
    578         @param section: A kernel section, either 'a' or 'b'.
    579         """
    580         self._kernel_handler.corrupt_kernel(section)
    581 
    582     @allow_multiple_section_input
    583     def _kernel_restore_sig(self, section):
    584         """Restore the requested kernel section (previously corrupted).
    585 
    586         @param section: A kernel section, either 'a' or 'b'.
    587         """
    588         self._kernel_handler.restore_kernel(section)
    589 
    590     def __kernel_modify_version(self, section, delta):
    591         """Modify kernel version for the requested section, by adding delta.
    592 
    593         The passed in delta, a positive or a negative number, is added to the
    594         original kernel version.
    595         """
    596         original_version = self._kernel_handler.get_version(section)
    597         new_version = original_version + delta
    598         self._os_if.log(
    599                 'Setting kernel section %s version from %d to %d' % (
    600                 section, original_version, new_version))
    601         self._kernel_handler.set_version(section, new_version)
    602 
    603     @allow_multiple_section_input
    604     def _kernel_move_version_backward(self, section):
    605         """Decrement kernel version for the requested section."""
    606         self.__kernel_modify_version(section, -1)
    607 
    608     @allow_multiple_section_input
    609     def _kernel_move_version_forward(self, section):
    610         """Increase kernel version for the requested section."""
    611         self.__kernel_modify_version(section, 1)
    612 
    613     def _kernel_get_version(self, section):
    614         """Return kernel version."""
    615         return self._kernel_handler.get_version(section)
    616 
    617     def _kernel_get_datakey_version(self, section):
    618         """Return kernel datakey version."""
    619         return self._kernel_handler.get_datakey_version(section)
    620 
    621     def _kernel_diff_a_b(self):
    622         """Compare kernel A with B.
    623 
    624         @return: True: if kernel A is different with B.
    625                  False: if kernel A is the same as B.
    626         """
    627         rootdev = self._os_if.get_root_dev()
    628         kernel_a = self._os_if.join_part(rootdev, '2')
    629         kernel_b = self._os_if.join_part(rootdev, '4')
    630 
    631         # The signature (some kind of hash) for the kernel body is stored in
    632         # the beginning. So compare the first 64KB (including header, preamble,
    633         # and signature) should be enough to check them identical.
    634         header_a = self._os_if.read_partition(kernel_a, 0x10000)
    635         header_b = self._os_if.read_partition(kernel_b, 0x10000)
    636 
    637         return header_a != header_b
    638 
    639     def _kernel_resign_with_keys(self, section, key_path=None):
    640         """Resign kernel with temporary key."""
    641         self._kernel_handler.resign_kernel(section, key_path)
    642 
    643     def _kernel_dump(self, section, kernel_path):
    644         """Dump the specified kernel to a file.
    645 
    646         @param section: The kernel to dump. May be A or B.
    647         @param kernel_path: The path to the kernel image to be written.
    648         """
    649         self._kernel_handler.dump_kernel(section, kernel_path)
    650 
    651     def _kernel_write(self, section, kernel_path):
    652         """Write a kernel image to the specified section.
    653 
    654         @param section: The kernel to dump. May be A or B.
    655         @param kernel_path: The path to the kernel image.
    656         """
    657         self._kernel_handler.write_kernel(section, kernel_path)
    658 
    659     def _kernel_get_sha(self, section):
    660         """Return the SHA1 hash of the specified kernel section."""
    661         return self._kernel_handler.get_sha(section)
    662 
    663     def _tpm_get_firmware_version(self):
    664         """Retrieve tpm firmware body version."""
    665         return self._tpm_handler.get_fw_version()
    666 
    667     def _tpm_get_firmware_datakey_version(self):
    668         """Retrieve tpm firmware data key version."""
    669         return self._tpm_handler.get_fw_key_version()
    670 
    671     def _tpm_get_kernel_version(self):
    672         """Retrieve tpm kernel body version."""
    673         return self._tpm_handler.get_kernel_version()
    674 
    675     def _tpm_get_kernel_datakey_version(self):
    676         """Retrieve tpm kernel data key version."""
    677         return self._tpm_handler.get_kernel_key_version()
    678 
    679     def _tpm_stop_daemon(self):
    680         """Stop tpm related daemon."""
    681         return self._tpm_handler.stop_daemon()
    682 
    683     def _tpm_restart_daemon(self):
    684         """Restart tpm related daemon which was stopped by stop_daemon()."""
    685         return self._tpm_handler.restart_daemon()
    686 
    687     def _cgpt_get_attributes(self):
    688         """Get kernel attributes."""
    689         rootdev = self._system_get_root_dev()
    690         self._cgpt_handler.read_device_info(rootdev)
    691         return {'A': self._cgpt_handler.get_partition(rootdev, 'KERN-A'),
    692                 'B': self._cgpt_handler.get_partition(rootdev, 'KERN-B')}
    693 
    694     def _cgpt_set_attributes(self, attributes):
    695         """Set kernel attributes."""
    696         rootdev = self._system_get_root_dev()
    697         allowed = ['priority', 'tries', 'successful']
    698         for p in ('A', 'B'):
    699             if p not in attributes:
    700                 continue
    701             attr = dict()
    702             for k in allowed:
    703                 if k in attributes[p]:
    704                     attr[k] = attributes[p][k]
    705             if attr:
    706                 self._cgpt_handler.set_partition(rootdev, 'KERN-%s' % p, attr)
    707 
    708     def _updater_cleanup(self):
    709         self._updater.cleanup_temp_dir()
    710 
    711     def _updater_stop_daemon(self):
    712         """Stop update-engine daemon."""
    713         return self._updater.stop_daemon()
    714 
    715     def _updater_start_daemon(self):
    716         """Start update-engine daemon."""
    717         return self._updater.start_daemon()
    718 
    719     def _updater_get_fwid(self):
    720         """Retrieve shellball's RW fwid.
    721 
    722         @return: Shellball's RW fwid.
    723         """
    724         return self._updater.retrieve_fwid()[1]
    725 
    726     def _updater_get_ecid(self):
    727         """Retrieve shellball's ecid.
    728 
    729         @return: Shellball's ecid.
    730         """
    731         return self._updater.retrieve_ecid()
    732 
    733     def _updater_modify_ecid_and_flash_to_bios(self):
    734         """Modify ecid, put it to AP firmware, and flash it to the system."""
    735         self._updater.modify_ecid_and_flash_to_bios()
    736 
    737     def _updater_get_ec_hash(self):
    738         """Return the hex string of the EC hash."""
    739         blob = self._updater.retrieve_ec_hash()
    740         # Format it to a hex string
    741         return ''.join('%02x' % ord(c) for c in blob)
    742 
    743     def _updater_resign_firmware(self, version):
    744         """Resign firmware with version.
    745 
    746         @param version: new version number.
    747         """
    748         self._updater.resign_firmware(version)
    749 
    750     def _updater_extract_shellball(self, append=None):
    751         """Extract shellball with the given append suffix.
    752 
    753         @param append: use for the shellball name.
    754         """
    755         self._updater.extract_shellball(append)
    756 
    757     def _updater_repack_shellball(self, append=None):
    758         """Repack shellball with new fwid.
    759 
    760         @param append: use for new fwid naming.
    761         """
    762         self._updater.repack_shellball(append)
    763 
    764     def _updater_run_autoupdate(self, append):
    765         """Run chromeos-firmwareupdate with autoupdate mode."""
    766         options = ['--noupdate_ec', '--wp=1']
    767         self._updater.run_firmwareupdate(mode='autoupdate',
    768                                          updater_append=append,
    769                                          options=options)
    770 
    771     def _updater_run_factory_install(self):
    772         """Run chromeos-firmwareupdate with factory_install mode."""
    773         options = ['--noupdate_ec', '--wp=0']
    774         self._updater.run_firmwareupdate(mode='factory_install',
    775                                          options=options)
    776 
    777     def _updater_run_bootok(self, append):
    778         """Run chromeos-firmwareupdate with bootok mode."""
    779         self._updater.run_firmwareupdate(mode='bootok',
    780                                          updater_append=append)
    781 
    782     def _updater_run_recovery(self):
    783         """Run chromeos-firmwareupdate with recovery mode."""
    784         options = ['--noupdate_ec', '--nocheck_keys', '--force', '--wp=1']
    785         self._updater.run_firmwareupdate(mode='recovery',
    786                                          options=options)
    787 
    788     def _updater_cbfs_setup_work_dir(self):
    789         """Sets up cbfstool work directory."""
    790         return self._updater.cbfs_setup_work_dir()
    791 
    792     def _updater_cbfs_extract_chip(self, fw_name):
    793         """Runs cbfstool to extract chip firmware.
    794 
    795         @param fw_name: Name of chip firmware to extract.
    796         @return: Boolean success status.
    797         """
    798         return self._updater.cbfs_extract_chip(fw_name)
    799 
    800     def _updater_cbfs_get_chip_hash(self, fw_name):
    801         """Gets the chip firmware hash blob.
    802 
    803         @param fw_name: Name of chip firmware whose hash blob to return.
    804         @return: Hex string of hash blob.
    805         """
    806         return self._updater.cbfs_get_chip_hash(fw_name)
    807 
    808     def _updater_cbfs_replace_chip(self, fw_name):
    809         """Runs cbfstool to replace chip firmware.
    810 
    811         @param fw_name: Name of chip firmware to extract.
    812         @return: Boolean success status.
    813         """
    814         return self._updater.cbfs_replace_chip(fw_name)
    815 
    816     def _updater_cbfs_sign_and_flash(self):
    817         """Runs cbfs signer and flash it.
    818 
    819         @param fw_name: Name of chip firmware to extract.
    820         @return: Boolean success status.
    821         """
    822         return self._updater.cbfs_sign_and_flash()
    823 
    824     def _updater_get_temp_path(self):
    825         """Get updater's temp directory path."""
    826         return self._updater.get_temp_path()
    827 
    828     def _updater_get_cbfs_work_path(self):
    829         """Get updater's cbfs work directory path."""
    830         return self._updater.get_cbfs_work_path()
    831 
    832     def _updater_get_keys_path(self):
    833         """Get updater's keys directory path."""
    834         return self._updater.get_keys_path()
    835 
    836     def _updater_get_work_path(self):
    837         """Get updater's work directory path."""
    838         return self._updater.get_work_path()
    839 
    840     def _updater_get_bios_relative_path(self):
    841         """Gets the relative path of the bios image in the shellball."""
    842         return self._updater.get_bios_relative_path()
    843 
    844     def _updater_get_ec_relative_path(self):
    845         """Gets the relative path of the ec image in the shellball."""
    846         return self._updater.get_ec_relative_path()
    847 
    848     def _rootfs_verify_rootfs(self, section):
    849         """Verifies the integrity of the root FS.
    850 
    851         @param section: The rootfs to verify. May be A or B.
    852         """
    853         return self._rootfs_handler.verify_rootfs(section)
    854 
    855     def _system_check_keys(self, expected_sequence):
    856         """Check the keys sequence was as expected.
    857 
    858         @param expected_sequence: A list of expected key sequences.
    859         """
    860         return self._check_keys.check_keys(expected_sequence)
    861 
    862     def cleanup(self):
    863         """Cleanup for the RPC server. Currently nothing."""
    864         pass
    865