#!/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


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('\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:]))
