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