blob: 2e5bc4c396ee651056bb63ba1697fdbfedc4bed3 [file] [log] [blame] [edit]
#!/usr/bin/env python3
# Copyright 2018 The ChromiumOS Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Verify flash protection
RO must not allow to boot RW with either ROLLBACK or RW unprotected
"""
from __future__ import print_function
import sys
import time
import common
import hammerd_api # pylint: disable=import-error
FLASH_PROTECT_INIT = (
common.EC_FLASH_PROTECT_RO_AT_BOOT
| common.EC_FLASH_PROTECT_RO_NOW
| common.EC_FLASH_PROTECT_ALL_NOW
| common.EC_FLASH_PROTECT_GPIO_ASSERTED
| common.EC_FLASH_PROTECT_ALL_AT_BOOT
| common.EC_FLASH_PROTECT_RW_AT_BOOT
| common.EC_FLASH_PROTECT_RW_NOW
| common.EC_FLASH_PROTECT_ROLLBACK_AT_BOOT
| common.EC_FLASH_PROTECT_ROLLBACK_NOW
)
FLASH_PROTECT_NORW = (
common.EC_FLASH_PROTECT_RO_AT_BOOT
| common.EC_FLASH_PROTECT_RO_NOW
| common.EC_FLASH_PROTECT_GPIO_ASSERTED
| common.EC_FLASH_PROTECT_ROLLBACK_AT_BOOT
| common.EC_FLASH_PROTECT_ROLLBACK_NOW
)
FLASH_PROTECT_NORB = (
common.EC_FLASH_PROTECT_RO_AT_BOOT
| common.EC_FLASH_PROTECT_RO_NOW
| common.EC_FLASH_PROTECT_GPIO_ASSERTED
| common.EC_FLASH_PROTECT_RW_AT_BOOT
| common.EC_FLASH_PROTECT_RW_NOW
)
def main(argv):
if argv:
sys.exit("Test takes no args!")
updater = common.get_firmware_updater()
# Load EC image.
with open(common.IMAGE, "rb") as f:
ec_image = f.read()
updater.LoadEcImage(ec_image)
common.disable_hammerd()
common.connect_usb(updater)
print(f"PDU Response: {updater.GetFirstResponsePdu().contents}")
print(f"Current running section: {updater.CurrentSection()}")
protect = get_flash_protection(updater)
print(f"Protection: {protect:04x} == {FLASH_PROTECT_INIT:04x}?")
assert protect == FLASH_PROTECT_INIT, "Initial WP status error"
unlock_rw(updater)
reset(updater)
updater.CloseUsb()
time.sleep(0.5)
# Catch it right after reset: RW is still unlocked and can be updated.
common.connect_usb(updater)
print(f"PDU Response: {updater.GetFirstResponsePdu().contents}")
print(f"Current running section: {updater.CurrentSection()}")
protect = get_flash_protection(updater)
print(f"Protection: {protect:04x} == {FLASH_PROTECT_NORW:04x}?")
assert protect == FLASH_PROTECT_NORW, "WP status after Unlock RW"
updater.CloseUsb()
time.sleep(common.WAIT_TIME_JUMP_FROM_RO_TO_RW)
# By now, hammer will have jumped to RW and locked the flash again
common.connect_usb(updater)
assert (
get_flash_protection(updater) == FLASH_PROTECT_INIT
), "WP status after jump RW"
updater.SendSubcommand(hammerd_api.UpdateExtraCommand.UnlockRollback)
reset(updater)
updater.CloseUsb()
time.sleep(0.5)
common.connect_usb(updater)
print(f"PDU Response: {updater.GetFirstResponsePdu().contents}")
print(f"Current running section: {updater.CurrentSection()}")
assert (
get_flash_protection(updater) == FLASH_PROTECT_NORB
), "WP status after Unlock RB"
updater.CloseUsb()
time.sleep(common.WAIT_TIME_JUMP_FROM_RO_TO_RW)
# By now, hammer will have jumped to RW and locked the flash again
common.connect_usb(updater)
assert (
get_flash_protection(updater) == FLASH_PROTECT_INIT
), "WP status after jump RW"
def get_flash_protection(updater):
pdu_resp = updater.GetFirstResponsePdu().contents
return pdu_resp.flash_protection
def reset(updater):
updater.SendSubcommand(hammerd_api.UpdateExtraCommand.ImmediateReset)
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(f"WP status: {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:]))