| #!/usr/bin/env python3 |
| # Copyright 2018 The Chromium OS Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| """Verify rollback update possible & flashing with lower rb version fails""" |
| |
| from __future__ import print_function |
| |
| import sys |
| import time |
| |
| import common |
| import hammerd_api |
| |
| # Before this test, please flash staff.dev.rb1 using servo |
| # This test can only be run once, then the image needs to be reflashed using |
| # servo again. |
| |
| def main(argv): |
| if argv: |
| sys.exit('Test takes no args!') |
| updater = hammerd_api.FirmwareUpdater(common.BASE_VENDOR_ID, |
| common.BASE_PRODUCT_ID, |
| common.BASE_USB_PATH) |
| # Load EC image. |
| with open(common.RB_INITIAL, 'rb') as f: |
| ec_image = f.read() |
| updater.LoadEcImage(ec_image) |
| |
| common.disable_hammerd() |
| |
| # Make sure rollback is updated to current RW image (rb1) |
| common.connect_usb(updater) |
| inc_rollback(updater, 1) |
| |
| # Update to invalid RW with RB < current RB |
| image_desc = 'Update to invalid RW with RB < current RB' |
| update_invalid_rb(updater, common.RB_LOWER, image_desc) |
| |
| # Restore to valid RB |
| image_desc = 'Restoring to valid RB_1 from RO' |
| restore_valid_rb(updater, common.RB_INITIAL, image_desc) |
| |
| # Update to valid RW with RB > current RB |
| image_desc = 'Update to valid RW with RB > current RB' |
| init_before_updaterw(updater) |
| common.reset_stay_ro(updater) |
| unlock_rw(updater) |
| restore_valid_rb(updater, common.RB_HIGHER, image_desc) |
| |
| # RB should now = RB_HIGHER |
| common.connect_usb(updater) |
| inc_rollback(updater, 9) |
| |
| |
| def init_before_updaterw(updater): |
| print('Calling init_before_updaterw') |
| common.connect_usb(updater) |
| print('EC information:') |
| pdu_resp = updater.GetFirstResponsePdu().contents |
| print('PDU Response: %s' % pdu_resp) |
| print('RO: %s' % updater.GetSectionVersion(hammerd_api.SectionName.RO)) |
| print('RW: %s' % updater.GetSectionVersion(hammerd_api.SectionName.RW)) |
| updater.SendFirstPdu() |
| updater.SendDone() |
| print('Current running section before RW: %s' % updater.CurrentSection()) |
| |
| |
| def transfer_rw(updater, image): |
| with open(image, 'rb') as f: |
| ec_image = f.read() |
| updater.LoadEcImage(ec_image) |
| print('Transferring RW') |
| updater.TransferImage(1) |
| updater.SendSubcommand(hammerd_api.UpdateExtraCommand.ImmediateReset) |
| updater.CloseUsb() |
| time.sleep(0.5) |
| common.connect_usb(updater) |
| updater.SendSubcommand(hammerd_api.UpdateExtraCommand.JumpToRW) |
| time.sleep(2) |
| updater.CloseUsb() |
| time.sleep(0.5) |
| # Jump to RW resets the base. Need to reconnect |
| common.connect_usb(updater) |
| print('PDU Response: %s' % updater.GetFirstResponsePdu().contents) |
| print('RO: %s' % updater.GetSectionVersion(hammerd_api.SectionName.RO)) |
| print('RW: %s' % updater.GetSectionVersion(hammerd_api.SectionName.RW)) |
| # Check that transferred RW is running if it's not corrupted version |
| updater.SendFirstPdu() |
| updater.SendDone() |
| print('Current running section after RW: %s' % updater.CurrentSection()) |
| |
| |
| def update_invalid_rb(updater, image, image_desc): |
| init_before_updaterw(updater) |
| common.reset_stay_ro(updater) |
| unlock_rw(updater) |
| print(image_desc) |
| transfer_rw(updater, image) |
| assert updater.CurrentSection() == 0, 'RW has lower RB version!' |
| |
| |
| def restore_valid_rb(updater, image, image_desc): |
| print(image_desc) |
| transfer_rw(updater, image) |
| common.sim_disconnect_connect(updater) |
| |
| |
| def get_wp_status(updater): |
| pdu_resp = updater.GetFirstResponsePdu().contents |
| wp_status = (pdu_resp.flash_protection & |
| common.EC_FLASH_PROTECT_GPIO_ASSERTED) > 0 |
| return wp_status |
| |
| |
| def unlock_rw(updater): |
| # Check if RW is locked and unlock if needed |
| wp = get_wp_status(updater) |
| print('WP status: %s' %str(wp)) |
| if wp: |
| print('Need to unlock RW') |
| updater.UnlockRW() |
| common.reset_stay_ro(updater) |
| |
| |
| def inc_rollback(updater, expected_rb): |
| current_rb = updater.GetFirstResponsePdu().contents.min_rollback |
| print('Current RB: %s' % current_rb) |
| updater.SendSubcommand(hammerd_api.UpdateExtraCommand.UnlockRollback) |
| common.sim_disconnect_connect(updater) |
| common.connect_usb(updater) |
| pdu_resp = updater.GetFirstResponsePdu().contents |
| print('PDU Response: %s' % pdu_resp) |
| print('Current running section: %s' % updater.CurrentSection()) |
| new_rb = updater.GetFirstResponsePdu().contents.min_rollback |
| print('New RB version: %s' % new_rb) |
| assert new_rb == expected_rb, 'Error: Failed to increment RB version!' |
| |
| if __name__ == '__main__': |
| sys.exit(main(sys.argv[1:])) |