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 11import traceback 12 13from 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 26def 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 45class 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