blob: 07b4295e8c212f463fd179d1f48c4eca1db6994f [file] [log] [blame]
#!/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 RO only boots valid RW and not corrupt/ dev signed RW"""
from __future__ import print_function
import sys
import time
import common
import hammerd_api
# Before this test, please flash MP-signed locked image (staff.bin)
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.RW_VALID, 'rb') as f:
ec_image = f.read()
updater.LoadEcImage(ec_image)
common.disable_hammerd()
# Update to invalid RW with corrupt bytes at begining of image
image_desc = 'Update to invalid RW with corrupt bytes at begining of image'
update_invalid_rw(updater, common.RW_CORRUPT_FIRST_BYTE, image_desc)
# Restore to valid RW
restore_valid_rw(updater, common.RW_VALID)
# Update to invalid RW with corrupt bytes at end of image
image_desc = 'Update to invalid RW with corrupt bytes at end of image'
update_invalid_rw(updater, common.RW_CORRUPT_LAST_BYTE, image_desc)
# Restore to valid RW
restore_valid_rw(updater, common.RW_VALID)
def init_before_updaterw(updater):
common.connect_usb(updater)
print('EC information:')
pdu_resp = updater.GetFirstResponsePdu().contents
print('PDU Response: %s' % pdu_resp)
print('Current section before updating RW: %s' % updater.CurrentSection())
assert updater.CurrentSection() == 1, 'Running section should be 1 (RW)'
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)
def update_invalid_rw(updater, image, image_desc):
init_before_updaterw(updater)
common.reset_stay_ro(updater)
unlock_rw(updater)
print(image_desc)
transfer_rw(updater, image)
updater.SendSubcommand(hammerd_api.UpdateExtraCommand.JumpToRW)
updater.CloseUsb()
# If successful (it should not be), jump to RW resets the base.
common.connect_usb(updater)
updater.SendFirstPdu()
updater.SendDone()
print('Current section-invalid RW update: %s' % updater.CurrentSection())
assert updater.CurrentSection() == 0, 'Running section should be 0 (RO)'
def restore_valid_rw(updater, image):
print('Restoring to valid RW')
transfer_rw(updater, image)
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)
updater.SendFirstPdu()
updater.SendDone()
print('Current section after valid RW update: %s' % updater.CurrentSection())
assert updater.CurrentSection() == 1, 'Running section should be 1 (RW)'
common.sim_disconnect_connect(updater)
def get_wp_status(updater):
wp_rw = (get_flash_protection(updater) & common.EC_FLASH_PROTECT_RW_NOW) > 0
return wp_rw
def get_flash_protection(updater):
pdu_resp = updater.GetFirstResponsePdu().contents
return pdu_resp.flash_protection
def unlock_rw(updater):
# Check if RW is locked and unlock if needed
wp_rw = (get_flash_protection(updater) & common.EC_FLASH_PROTECT_RW_NOW) > 0
print('WP status: %s' %str(wp_rw))
if wp_rw:
print('Need to unlock RW')
unlocked = updater.UnlockRW()
assert unlocked == 1, 'Failed to unlock RW'
common.reset_stay_ro(updater)
if __name__ == '__main__':
sys.exit(main(sys.argv[1:]))