#!/usr/bin/env python2
# 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 can update RW

Uses two different fw images with the same rollback version
'''

from __future__ import print_function

import sys
import time

import common
import hammerd_api


def main(argv):
  if len(argv) > 0:
    sys.exit('Test takes no args!')
  updater = hammerd_api.FirmwareUpdater(common.BASE_VENDOR_ID,
                                        common.BASE_PRODUCT_ID,
                                        common.BASE_BUS,
                                        common.BASE_PORT)
  # Load EC image.
  with open(common.OLDER_IMAGE, 'rb') as f:
    ec_image = f.read()
  updater.LoadEcImage(ec_image)

  common.disable_hammerd()
  init_before_updaterw(updater)
  common.reset_stay_ro(updater)
  unlock_rw(updater)
  print('Updating to OLDER_IMAGE fw from RO')
  transfer_rw(updater, common.OLDER_IMAGE)
  common.sim_disconnect_connect(updater)

  common.disable_hammerd()
  init_before_updaterw(updater)
  common.reset_stay_ro(updater)
  unlock_rw(updater)
  print('Updating to NEWER_IMAGE from RO')
  transfer_rw(updater, common.NEWER_IMAGE)
  common.sim_disconnect_connect(updater)


def init_before_updaterw(updater):
  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('Current running section before RW jump: %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)
  # Check that transferred RW is running
  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))
  updater.SendFirstPdu()
  updater.SendDone()
  print('Current running section after RW jump: %s' % updater.CurrentSection())


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)

if __name__ == '__main__':
  sys.exit(main(sys.argv[1:]))
