blob: 952994ab984dd1cd863c97af9b861ba0f866177d [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 that RO cannot flash to wrong address. Test needs unlocked image"""
from __future__ import print_function
import sys
import time
import common
import hammerd_api # pylint: disable=import-error
WRONG_ADDRR_KEY_RO = '0x0000ac00'
WRONG_ADDRR_RO_FRID = '0x000000c4'
WRONG_ADDRR_RW_FWID = '0x0000c0c4'
WRONG_ADDRR_SIG_RW = '0x0001fc00'
WRONG_ADDRR_RW_RBVER = '0x0000c0e8'
RIGHT_ADDRR_RW_OFFSET = '0x0000c000'
WRONG_ADDR_LIST = [WRONG_ADDRR_RW_FWID,
WRONG_ADDRR_SIG_RW,
WRONG_ADDRR_RW_RBVER]
# WRONG_ADDR_LIST = [WRONG_ADDRR_KEY_RO, WRONG_ADDRR_RO_FRID]
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)
# Use unlocked image on dut to verify that TransferTouchpadFirmware call works
with open(common.IMAGE, 'rb') as f:
ec_image = f.read()
updater.LoadEcImage(ec_image)
common.disable_hammerd()
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))
print('Is RW locked?: %s' % updater.IsSectionLocked(1))
updater.SendSubcommand(hammerd_api.UpdateExtraCommand.ImmediateReset)
updater.CloseUsb()
time.sleep(0.5)
updater.TryConnectUsb()
updater.SendSubcommand(hammerd_api.UpdateExtraCommand.StayInRO)
time.sleep(1)
assert updater.SendFirstPdu() is True, 'Error sending first PDU'
updater.SendDone()
print('Current section after StayInRO cmd: %s' % updater.CurrentSection())
assert updater.CurrentSection() == 0, 'Running section should be 0 (RO)'
init_tp_transfer(updater)
# Try to flash to invalid addresses. Since image is unlocked this should flash
flash_invalid_image(updater)
# Restore valid RW
restore_valid_rw(updater, common.IMAGE)
def flash_invalid_image(updater):
# Check that TransferTouchpadFirmware can write to RW in unlocked image
for address in WRONG_ADDR_LIST:
common.connect_usb(updater)
unlock_rw(updater)
wr = updater.TransferTouchpadFirmware(int(address, 0), 1)
assert wr == 1, 'Cannot write to flash: Is DUT image unlocked?'
assert updater.SendFirstPdu() is True, 'Error sending first PDU'
updater.SendDone()
print('Current section: %s' % updater.CurrentSection())
assert updater.CurrentSection() == 0, 'Running section should be 0 (RO)'
updater.SendSubcommand(hammerd_api.UpdateExtraCommand.ImmediateReset)
updater.CloseUsb()
time.sleep(0.5)
def restore_valid_rw(updater, image):
print('Restoring to valid RW')
common.connect_usb(updater)
updater.SendSubcommand(hammerd_api.UpdateExtraCommand.StayInRO)
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)
assert updater.SendFirstPdu() is True, 'Error sending first PDU'
updater.SendDone()
print('Current section after valid RW: %s' % updater.CurrentSection())
assert updater.CurrentSection() == 1, 'Running section should be 1 (RW)'
common.sim_disconnect_connect(updater)
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 init_tp_transfer(updater):
updater.LoadTouchpadImage(b'\x00')
assert updater.SendFirstPdu() is True, 'Error sending first PDU'
updater.SendDone()
unlock_rw(updater)
def get_flash_protection(updater):
pdu_resp = updater.GetFirstResponsePdu().contents
return pdu_resp.flash_protection
def get_wp_status(updater):
wp_rw = (get_flash_protection(updater) & common.EC_FLASH_PROTECT_RW_NOW) > 0
return wp_rw
def unlock_rw(updater):
# Check if RW is locked and unlock if needed
wp_rw = get_wp_status(updater)
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'
if __name__ == '__main__':
sys.exit(main(sys.argv[1:]))