| OLD | NEW |
| 1 #!/usr/bin/python | 1 #!/usr/bin/python |
| 2 # Copyright (c) 2010 The Chromium OS Authors. All rights reserved. | 2 # Copyright (c) 2010 The Chromium OS Authors. All rights reserved. |
| 3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
| 4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
| 5 | 5 |
| 6 '''Test utility for verifying ChromeOS firmware.''' | 6 '''Test utility for verifying ChromeOS firmware.''' |
| 7 | 7 |
| 8 import datetime | 8 import datetime |
| 9 import functools | 9 import functools |
| 10 import getopt | 10 import getopt |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 90 STEP_FILE = 'fw_test_step' # The next test step number. | 90 STEP_FILE = 'fw_test_step' # The next test step number. |
| 91 FW_BACKUP_FILE = 'flashrom.bak' # Preserved original flashrom contents. | 91 FW_BACKUP_FILE = 'flashrom.bak' # Preserved original flashrom contents. |
| 92 FW_COPY_FILE = 'flashrom.new' # A copy of the flashrom contents being tested. | 92 FW_COPY_FILE = 'flashrom.new' # A copy of the flashrom contents being tested. |
| 93 FWID_BACKUP_FILE = 'fwid.bak' # FWID reported by the original firmware. | 93 FWID_BACKUP_FILE = 'fwid.bak' # FWID reported by the original firmware. |
| 94 FWID_NEW_FILE = 'fwid.new' # FWID reported by the firmware being tested. | 94 FWID_NEW_FILE = 'fwid.new' # FWID reported by the firmware being tested. |
| 95 | 95 |
| 96 BASE_STORAGE_DEVICE = '/dev/sda' | 96 BASE_STORAGE_DEVICE = '/dev/sda' |
| 97 | 97 |
| 98 # The list of shell executables necessary for this program to work. | 98 # The list of shell executables necessary for this program to work. |
| 99 REQUIRED_PROGRAMS = ''' | 99 REQUIRED_PROGRAMS = ''' |
| 100 cgpt blkid flashrom reboot_mode readlink rootdev vbutil_firmware vbutil_kernel | 100 cgpt crossystem blkid flashrom readlink rootdev vbutil_firmware vbutil_kernel |
| 101 mosys | 101 mosys |
| 102 ''' | 102 ''' |
| 103 | 103 |
| 104 | 104 |
| 105 FLASHROM_HANDLER = flashrom_handler.FlashromHandler() | 105 FLASHROM_HANDLER = flashrom_handler.FlashromHandler() |
| 106 CHROS_IF = chromeos_interface.ChromeOSInterface(__name__ != '__main__') | 106 CHROS_IF = chromeos_interface.ChromeOSInterface(__name__ != '__main__') |
| 107 cgpt_st = cgpt_state.CgptState('COMPLETE', CHROS_IF, BASE_STORAGE_DEVICE) | 107 cgpt_st = cgpt_state.CgptState('COMPLETE', CHROS_IF, BASE_STORAGE_DEVICE) |
| 108 | 108 |
| 109 def allow_multiple_section_input(image_operator): | 109 def allow_multiple_section_input(image_operator): |
| 110 @functools.wraps(image_operator) | 110 @functools.wraps(image_operator) |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 168 self.window = None | 168 self.window = None |
| 169 self.tpm_handler = None | 169 self.tpm_handler = None |
| 170 | 170 |
| 171 def _verify_fw_id(self, compare_to_file): | 171 def _verify_fw_id(self, compare_to_file): |
| 172 '''Verify if the current firmware ID matches the contents a file. | 172 '''Verify if the current firmware ID matches the contents a file. |
| 173 | 173 |
| 174 compare_to_file - a string, name of the file in the state directory. | 174 compare_to_file - a string, name of the file in the state directory. |
| 175 ''' | 175 ''' |
| 176 old_fwid = open( | 176 old_fwid = open( |
| 177 self.chros_if.state_dir_file(compare_to_file), 'r').read() | 177 self.chros_if.state_dir_file(compare_to_file), 'r').read() |
| 178 now_fwid = open(self.chros_if.acpi_file('FWID'), 'r').read() | 178 now_fwid = self.chros_if.cs.fwid |
| 179 return old_fwid == now_fwid | 179 return old_fwid == now_fwid |
| 180 | 180 |
| 181 def _get_step(self): | 181 def _get_step(self): |
| 182 '''Set the current value of SAFT step number.''' | 182 '''Set the current value of SAFT step number.''' |
| 183 step_file = self.chros_if.state_dir_file(STEP_FILE) | 183 step_file = self.chros_if.state_dir_file(STEP_FILE) |
| 184 step = open(step_file, 'r').read().strip() | 184 step = open(step_file, 'r').read().strip() |
| 185 return int(step) | 185 return int(step) |
| 186 | 186 |
| 187 def _set_step(self, step): | 187 def _set_step(self, step): |
| 188 '''Set the SAFT step number to control the next test pass.''' | 188 '''Set the SAFT step number to control the next test pass.''' |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 245 | 245 |
| 246 os.rmdir(tmp_dir) | 246 os.rmdir(tmp_dir) |
| 247 | 247 |
| 248 def _check_runtime_env(self): | 248 def _check_runtime_env(self): |
| 249 '''Ensure that the script is running in proper environment. | 249 '''Ensure that the script is running in proper environment. |
| 250 | 250 |
| 251 This involves checking that the script is running off a removable | 251 This involves checking that the script is running off a removable |
| 252 device, configuring proper file names for logging, etc. | 252 device, configuring proper file names for logging, etc. |
| 253 ''' | 253 ''' |
| 254 line = self.chros_if.run_shell_command_get_output( | 254 line = self.chros_if.run_shell_command_get_output( |
| 255 'df %s' % self.mydir)[-1] | 255 'df %s' % self.mydir)[1] |
| 256 | 256 |
| 257 self.base_partition = line.split()[0] | 257 self.base_partition = line.split()[0] |
| 258 if self.base_partition == '/dev/root': | 258 if self.base_partition == '/dev/root': |
| 259 self.base_partition = self.chros_if.get_root_dev() | 259 self.base_partition = self.chros_if.get_root_dev() |
| 260 | 260 |
| 261 if not self.chros_if.is_removable_device(self.base_partition): | 261 if not self.chros_if.is_removable_device(self.base_partition): |
| 262 raise FwError( | 262 raise FwError( |
| 263 'This test must run off a removable device, not %s' | 263 'This test must run off a removable device, not %s' |
| 264 % self.base_partition) | 264 % self.base_partition) |
| 265 | 265 |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 336 if self.kern_handler: | 336 if self.kern_handler: |
| 337 vers_a = self.kern_handler.get_version('a') | 337 vers_a = self.kern_handler.get_version('a') |
| 338 vers_b = self.kern_handler.get_version('b') | 338 vers_b = self.kern_handler.get_version('b') |
| 339 if not self.tpm_handler.kernel_version_good(vers_a, vers_b): | 339 if not self.tpm_handler.kernel_version_good(vers_a, vers_b): |
| 340 raise FwError('TPM kernel version mismatch (%d %d %s)' %
( | 340 raise FwError('TPM kernel version mismatch (%d %d %s)' %
( |
| 341 vers_a, vers_b, self.base_partition)) | 341 vers_a, vers_b, self.base_partition)) |
| 342 | 342 |
| 343 def set_try_fw_b(self): | 343 def set_try_fw_b(self): |
| 344 '''Request running firmware B on the next restart.''' | 344 '''Request running firmware B on the next restart.''' |
| 345 self.chros_if.log('Requesting restart with FW B') | 345 self.chros_if.log('Requesting restart with FW B') |
| 346 self.chros_if.run_shell_command('reboot_mode --try_firmware_b=1') | 346 self.chros_if.cs.fwb_tries = 1 |
| 347 | 347 |
| 348 def request_recovery_boot(self): | 348 def request_recovery_boot(self): |
| 349 '''Request running in recovery mode on the restart.''' | 349 '''Request running in recovery mode on the restart.''' |
| 350 self.chros_if.log('Requesting restart in recovery mode') | 350 self.chros_if.log('Requesting restart in recovery mode') |
| 351 self.chros_if.run_shell_command('reboot_mode --recovery=1') | 351 self.chros_if.cs.request_recovery() |
| 352 |
| 352 | 353 |
| 353 @allow_multiple_section_input | 354 @allow_multiple_section_input |
| 354 def restore_firmware(self, section): | 355 def restore_firmware(self, section): |
| 355 '''Restore the requested firmware section (previously corrupted).''' | 356 '''Restore the requested firmware section (previously corrupted).''' |
| 356 self.chros_if.log('Restoring firmware %s' % section) | 357 self.chros_if.log('Restoring firmware %s' % section) |
| 357 FLASHROM_HANDLER.restore_firmware(section) | 358 FLASHROM_HANDLER.restore_firmware(section) |
| 358 | 359 |
| 359 @allow_multiple_section_input | 360 @allow_multiple_section_input |
| 360 def corrupt_firmware(self, section): | 361 def corrupt_firmware(self, section): |
| 361 '''Corrupt the requested firmware section.''' | 362 '''Corrupt the requested firmware section.''' |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 522 datetime.datetime.strftime( | 523 datetime.datetime.strftime( |
| 523 datetime.datetime.now(), '%b %d %Y'))) | 524 datetime.datetime.now(), '%b %d %Y'))) |
| 524 chros_if.log('Original boot state %s' % chros_if.boot_state_vector()) | 525 chros_if.log('Original boot state %s' % chros_if.boot_state_vector()) |
| 525 self.chros_if = chros_if | 526 self.chros_if = chros_if |
| 526 fw_image = opt_dictionary['image_file'] | 527 fw_image = opt_dictionary['image_file'] |
| 527 self.new_fw_image() | 528 self.new_fw_image() |
| 528 FLASHROM_HANDLER.dump_whole( | 529 FLASHROM_HANDLER.dump_whole( |
| 529 self.chros_if.state_dir_file(FW_BACKUP_FILE)) | 530 self.chros_if.state_dir_file(FW_BACKUP_FILE)) |
| 530 self.new_fw_image(fw_image) | 531 self.new_fw_image(fw_image) |
| 531 self._handle_saft_script(True) | 532 self._handle_saft_script(True) |
| 532 shutil.copyfile(self.chros_if.acpi_file('FWID'), | 533 open(self.chros_if.state_dir_file(FWID_BACKUP_FILE), 'w' |
| 533 self.chros_if.state_dir_file(FWID_BACKUP_FILE)) | 534 ).write(self.chros_if.cs.fwid) |
| 534 shutil.copyfile(fw_image, self.chros_if.state_dir_file(FW_COPY_FILE)) | 535 shutil.copyfile(fw_image, self.chros_if.state_dir_file(FW_COPY_FILE)) |
| 535 | 536 |
| 536 self._set_step(0) | 537 self._set_step(0) |
| 537 cgpt_st.set_step(0) | 538 cgpt_st.set_step(0) |
| 538 | 539 |
| 539 def next_step(self): | 540 def next_step(self): |
| 540 '''Function to execute a single SAFT step. | 541 '''Function to execute a single SAFT step. |
| 541 | 542 |
| 542 This function is running after each reboot. It determines the current | 543 This function is running after each reboot. It determines the current |
| 543 step the SAFT is on, executes the appropriate action, increments the | 544 step the SAFT is on, executes the appropriate action, increments the |
| 544 step value and then restats the machine. | 545 step value and then restats the machine. |
| 545 ''' | 546 ''' |
| 546 | 547 |
| 547 this_step = self._get_step() | 548 this_step = self._get_step() |
| 548 | 549 |
| 549 # Import when needed, because otherwise running test generates a | 550 # Import when needed, because otherwise running test generates a |
| 550 # warning exception about the unavailable display. | 551 # warning exception about the unavailable display. |
| 551 window = __import__('window') | 552 window = __import__('window') |
| 552 self.window = window.GraphThread() | 553 self.window = window.GraphThread() |
| 553 | 554 |
| 554 if this_step == 0: | 555 if this_step == 0: |
| 555 shutil.copyfile(self.chros_if.acpi_file('FWID'), | 556 open(self.chros_if.state_dir_file(FWID_NEW_FILE), 'w' |
| 556 self.chros_if.state_dir_file(FWID_NEW_FILE)) | 557 ).write(self.chros_if.cs.fwid) |
| 557 | 558 |
| 558 if self._verify_fw_id(FWID_BACKUP_FILE): | 559 if self._verify_fw_id(FWID_BACKUP_FILE): |
| 559 # we expected FWID to change, but it did not - have the firmware | 560 # we expected FWID to change, but it did not - have the firmware |
| 560 # been even replaced? | 561 # been even replaced? |
| 561 self.chros_if.log('New firmware - old FWID') | 562 self.chros_if.log('New firmware - old FWID') |
| 562 self.finish_saft(False) | 563 self.finish_saft(False) |
| 563 test_state_tuple = self.test_state_sequence[this_step] | 564 test_state_tuple = self.test_state_sequence[this_step] |
| 564 expected_vector = test_state_tuple[0] | 565 expected_vector = test_state_tuple[0] |
| 565 action = test_state_tuple[1] | 566 action = test_state_tuple[1] |
| 566 | 567 |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 634 # Have chros_if.shutdown move the log into the '/var' directory to | 635 # Have chros_if.shutdown move the log into the '/var' directory to |
| 635 # make it easier to see SAFT results. | 636 # make it easier to see SAFT results. |
| 636 self.chros_if.shut_down(os.path.join('/var', LOG_FILE)) | 637 self.chros_if.shut_down(os.path.join('/var', LOG_FILE)) |
| 637 | 638 |
| 638 self.window.stop() | 639 self.window.stop() |
| 639 sys.exit(0) | 640 sys.exit(0) |
| 640 | 641 |
| 641 # Firmware self test instance controlling this module. | 642 # Firmware self test instance controlling this module. |
| 642 FST = FirmwareTest() | 643 FST = FirmwareTest() |
| 643 | 644 |
| 644 # This is a tuple of tuples controlling the SAFT state machine. The states | 645 # This is a tuple of tuples controlling the SAFT state machine. The states are |
| 645 # are expected to be passed strictly in order. The states are identified | 646 # expected to be passed strictly in order. The states used to be identified by |
| 646 # by the contents of BINF.[012] files in the sys fs ACPI directory. The | 647 # the contents of BINF.[012] files in the sys fs ACPI directory. Now they are |
| 647 # BINF files store information about the reason for reboot, what | 648 # derived from the crossystem output to match previously reported states. |
| 648 # firmware/kernel partitions were used, etc. | |
| 649 # | 649 # |
| 650 # The first element of each component tuple is the expected state of the | 650 # The first element of each component tuple is the expected state of the |
| 651 # machine (a ':' concatenation of the BINF files' contents). | 651 # machine. |
| 652 # | 652 # |
| 653 # The second element of the component tuples is the action to take to | 653 # The second element of the component tuples is the action to take to |
| 654 # advance the test. The action is a function to call. The last line has | 654 # advance the test. The action is a function to call. The last line has |
| 655 # action set to None, which indicates to the state machine that the test | 655 # action set to None, which indicates to the state machine that the test |
| 656 # is over. | 656 # is over. |
| 657 # | 657 # |
| 658 # The third component, if present, is the parameter to pass to the action | 658 # The third component, if present, is the parameter to pass to the action |
| 659 # function. | 659 # function. |
| 660 | 660 |
| 661 TEST_STATE_SEQUENCE = ( | 661 TEST_STATE_SEQUENCE = ( |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 768 if 'next_step' in opt_dictionary: | 768 if 'next_step' in opt_dictionary: |
| 769 if len(opt_dictionary) != 1: | 769 if len(opt_dictionary) != 1: |
| 770 usage('--next_step (when specified) must be the only parameter', 1) | 770 usage('--next_step (when specified) must be the only parameter', 1) |
| 771 try: | 771 try: |
| 772 FST.next_step() | 772 FST.next_step() |
| 773 except SystemExit: | 773 except SystemExit: |
| 774 pass # No real exception, this is just an exit (for whatever | 774 pass # No real exception, this is just an exit (for whatever |
| 775 # reason), gtk window already closed. | 775 # reason), gtk window already closed. |
| 776 except: | 776 except: |
| 777 # Whatever error that might be, gtk window must be shut. | 777 # Whatever error that might be, gtk window must be shut. |
| 778 FST.window.stop() | 778 if FST.window: |
| 779 FST.window.stop() |
| 779 | 780 |
| 780 # Make sure exception information is saved in the log. | 781 # Make sure exception information is saved in the log. |
| 781 exc_type, exc_info, exc_trace = sys.exc_info() | 782 exc_type, exc_info, exc_trace = sys.exc_info() |
| 782 print 'exception type:', str(exc_type) | 783 print 'exception type:', str(exc_type) |
| 783 print 'exception info:', str(exc_info) | 784 print 'exception info:', str(exc_info) |
| 784 traceback.print_tb(exc_trace) | 785 traceback.print_tb(exc_trace) |
| 785 sys.exit(0) | 786 sys.exit(0) |
| 786 | 787 |
| 787 # check if all executables are available | 788 # check if all executables are available |
| 788 missing_execs = [] | 789 missing_execs = [] |
| (...skipping 30 matching lines...) Expand all Loading... |
| 819 main(sys.argv) | 820 main(sys.argv) |
| 820 except (getopt.GetoptError, ImportError): | 821 except (getopt.GetoptError, ImportError): |
| 821 usage(sys.exc_info()[1], 1) | 822 usage(sys.exc_info()[1], 1) |
| 822 except (FwError, flashrom_handler.FlashromHandlerError): | 823 except (FwError, flashrom_handler.FlashromHandlerError): |
| 823 MSG = 'Error: %s' % str(sys.exc_info()[1]) | 824 MSG = 'Error: %s' % str(sys.exc_info()[1]) |
| 824 print MSG | 825 print MSG |
| 825 CHROS_IF.log(MSG) | 826 CHROS_IF.log(MSG) |
| 826 sys.exit(1) | 827 sys.exit(1) |
| 827 | 828 |
| 828 sys.exit(0) | 829 sys.exit(0) |
| OLD | NEW |