#!/usr/bin/env python
# Copyright (c) 2021 Qualcomm Technologies, Inc.  All Rights Reserved.
# Qualcomm Technologies Proprietary and Confidential.

try:
  from SecureAppMetadata import *
except ImportError as e:
  print("Unable to regenerate service to uid mapping.\
        qteeConfigInfo can still be generated but may not be up to date.", e)

import os
import sys
import re
import argparse
import json
from collections import defaultdict

# This dictionary is populated with services as keys and their UIDs as values
idl_mapping = {"getrotta":16711693,"memregiontester":16711688,"invoketest1":16711687,"strongboxemulator":631,"tpmnvstorage":137,"dummyservice":16715776,"getcredentials":16711953,"testsandbox":16711681,"testsmcinvoke":16711703,"retstaappdummyservice":16711710,"embeddedtatest1":16711727,"embeddedtatest":16711711,"embeddedtatest2":16711721,"invoketest":16711686,"sharedbufferproxytest":16711706,"getrotta1":16711692,"sharedbufferproxywlbypasstest":16711707,"vmfiletransferservice":252,"tunnelinvokemgr":124,"resettimer":44,"hwkeyfactoryprivate":302,"hwkeyfactoryasym":303,"sc_proxy":161,"registerapp":263,"tpmconfig":248,"display":300,"dh_rtic":70,"securechannelkeysetupmdm":359,"qweskernelservice":171,"preuefifwhash":104,"tacounter":139,"tmecomtest":16711851,"qseecomcompatapploader":122,"tamemoryspace":6,"peripheralevent_modem":1537,"asymcryptoecc":135,"peripheralretainstate":269,"softskuta":291,"tprelauncher":329,"commonlib":4,"securechannelkeysetupapq":358,"gpcommonlib":5,"videosharedmemory":156,"watchdog":24,"softskusvc":287,"peripheralsecurityattestation":285,"scp11crypto":141,"tpowerservice":331,"fipstest":16711754,"app":0,"tprivilegedprocessmanager":328,"gpappclient":409,"tunnelinvokegetpeer":123,"taccesscontrol":330,"platforminfo":278,"sheservice":613,"demuratnservice":253,"softsku_ta":273,"celerityproperty":75,"pmic":259,"she":210,"trusteduilistener":262,"gpinternal":32,"fe":254,"softsku":256,"keymasterapp":121,"strongbox":136,"strongboxprovisioner":175,"keyprotect":1201,"tzsc":160,"deprecated_77":77,"deprecated_1026":1026,"ttouchcontrolservice":304,"minidumpcompressservice":1023,"pfm":119,"deviceregion_mdss":100,"oembuf":52,"listener":48,"keymanager":110,"keygen":1027,"opssink":91,"vmsessionkey":261,"securecamera":56,"oemunwrapkeys":1024,"secstorage":145,"rticdtb":112,"guestvm":63,"cpapprwauthority":632,"tzerrordiaginfocallback":281,"secureimage":3295,"legacysandbox":129,"sharedbuffer":23,"cryptoselftest":133,"accesscontrol":138,"hdcp_r1":66,"securecamera2oemvmapp":294,"defunctvmqteeresource":353,"runtimeattestation":307,"whitelistbypass":128,"swfuse":22,"registertabufcbo":268,"ice":140,"system":130,"tregistermodule":326,"venussecurechannel":95,"crypto":11,"swcrypto":511,"tsens":144,"pvc":14,"hdcpencryption":65,"rpmbservice":274,"peripheralaccesscontrol_audio":1281,"peripheralaccesscontrol_bluetooth":1282,"peripheralaccesscontrol_camera":1283,"peripheralaccesscontrol_modem":1284,"peripheralaccesscontrol_gnss":1285,"peripheralaccesscontrol_nfc":1286,"peripheralaccesscontrol_usb":1287,"peripheralaccesscontrol_wifi":1288,"tpm":81,"whitelistbypassro":134,"cpnonpixelrwauthority":27,"appclient":151,"privacypreservingid":455,"qwestaservices":120,"uptime":18,"cpbitstreamrwauthority":10,"storageaccess":356,"transnsaddr":54,"tprocessloader":324,"videosecurechannel":195,"legacyhwattestation":111,"memregionpermescalator":8,"trusteduiapp":292,"licensemanager":80,"diagnostics":143,"diagfuseservice":265,"debugpolicysource":64,"connsec":101,"qrks":71,"securechannel":26,"credentials":180,"nsmem":15,"hdcpsrm":93,"hwfuse":28,"oemfidoconfig":1025,"oemhyptotaservice":1028,"spcom":55,"registerqteecallback":276,"featureversions":2033,"nssystemreg":96,"sync":51,"rkpbcc":297,"computedspsecurememaccess":83,"tlockey":113,"hlosregionfinder":132,"kmhal":150,"spi":16,"kvstoreadmin":900,"rticreport":98,"eseservice":255,"opssource":92,"clockconfig":97,"certification":310,"securedspservice":400,"securechannelkeyexchange":639,"hdcp_r2p2":69,"registerlistenercbo":87,"time":270,"irisapp":279,"hashnone":38,"hashsha1":39,"hashsha256":40,"hashsha384":46,"hashsha512":47,"hashsm3":267,"hashsha3_224":343,"hashsha3_256":344,"hashsha3_384":346,"hashsha3_512":347,"trustedcameradriver":283,"decryptimageservice":282,"datacache":19,"hdmistatus":13,"memoryservice":325,"securedisplay":25,"haventokenapp":78,"vmdeviceuniquekey":345,"ipprotector":82,"swcryptoecc":309,"deviceregion_scc":103,"hmacsha1":41,"hmacsha256":42,"hmacsha384":60,"hmacsha512":61,"hmacsha3_224":348,"hmacsha3_256":349,"hmacsha3_384":351,"hmacsha3_512":352,"heliosapp":286,"pmpon":350,"tlmm":45,"watchdogfactory":257,"pvclicense":34,"scpassthrough":102,"dspsharedchannel":84,"dspsharedchannel2":88,"cpzlicense":811,"sandbox":131,"secureimageparser":3054,"loadalgota":401,"certvalidate":50,"deviceid":12,"updaterollbackversion":299,"secureimageprivate":3296,"securecamera2app":293,"tuicoreservice":288,"ops":90,"hwkeyfactory":301,"macchiato":49,"cpcamerarwauthority":289,"qteeenvinfo":29,"filetable":306,"appmessage":21,"securecamera2":57,"prngsource":17,"deviceattestation":62,"i2c":43,"devicedebuginfo":295,"connectionsecurity":275,"apploader":3,"cipheraes128":35,"cipheraes256":36,"ciphertripledes":37,"ciphersm4":266,"touchinput":290,"deviceregionfinder":99,"kvstore":9,"intmask":53,"storrd":162,"trustedcameramemory":357,"peripheralstate":264,"embeddedmissingneverunload":16711746,"objectsink":16711705,"testinvoker":16711698,"embeddedcommontestservice":16711745,"embeddedstresstestservice":16711749,"lateregistration":16711765,"perftest":16773393,"sparetestservice":16711763,"embeddedwrongtestservice":16711750,"stresstestservice":16711764,"pvclicensectrl":16711690,"asyncreleasetest":16711704,"testkregionqteemap":16711724,"stacktest":16711713,"tzdiaginfo":16711712,"testclientvm":16711726,"appregiontest":16711708,"testparams":16711683,"qteedebuginfo":16711709,"embeddednormaldeathtestservice":16711747,"testdeviceregion":16711701,"minkthreadtest":16711719,"embeddedlateregistration":16711752,"credentialsfromkernelclienttest":16711728,"testtalog":16711716,"creddealertestservice":16711762,"credentialsgetter":16711696,"test1":16711684,"memperftest":16711702,"testreerequestcleanup":16711717,"memregionallocator":16711689,"qteetestmodifier":16711691,"observer":16711685,"testcback":16711694,"statictestcback":16711718,"sampleservice":16711743,"testlistenercbos":16711699,"embeddedsparetestservice":16711748,"testwaitq":16711720,"embeddedallprivilegetestservice":16711744,"testlock":16711697,"commontestservice":16711761,"testyield":16711700,"objforwarder":16711695,"allprivilegetestservice":16711760}

def exists(env):
    return True

def generate(env):
  generator(env)

def generator(env):
  env.AddMethod(generate_vm_qtee_config_info_builder, "GenerateVMQteeConfigInfoBuilder")

def generate_vm_qtee_config_info_builder(env, target, source):
  idl_class_ids = IDLScanner()._generate_class_id_map(source)
  cur_file = read_self()
  # Getting the index of the idl_mapping line
  target_line = [index for index, string in enumerate(cur_file) if 'idl_mapping = {' in string][0]
  # Constructing new idl_mapping line
  line = 'idl_mapping = {'
  for service, uid in idl_class_ids.items():
    line+=("\"" + service + "\":" + str(uid) + ",")
  line = line[:-1]
  line+=("}\n")
  if cur_file[target_line] != line:
    cur_file[target_line] = line
    write_self_to_target(cur_file, target)

def generate_cclent_env_perms(source, idl_map):
  out_dict = defaultdict(str)
  perms_by_vm = json.loads(source.read())

  for vm in perms_by_vm:
    # Removing the 'C' and _UID from each service permission in the list
    perms_by_vm[vm] = [mdperm.strip()[1:-4].lower() for mdperm in perms_by_vm[vm]]
    try:
      # Converting the services into the serialized string
      enabled_perms = sorted(set(hex(idl_map[uid.lower()]).replace('0x','').upper() for uid in perms_by_vm[vm]),key=lambda x: int(x,16))
      permissions_str = '\"p=' + ','.join(enabled_perms) + ';\"'
      out_dict[vm] = permissions_str
    except KeyError as e:
      print("Unable to find Service name, please make sure it has access to a REE.", e)
      exit(1)
  return out_dict

def read_self():
  # Reading the current file to copy to the build dir
  contents = []
  with open(__file__, "r") as f:
    for line in f:
      contents.append(line)
  return contents

def write_self_to_target(contents, target):
  with open(target, "w") as f:
    for line in contents:
      f.write(line)

def is_file_valid(parser, arg):
  if not os.path.exists(arg):
    parser.error("Can not find file %s\n" % arg)
  else:
    return open(arg, 'r')

def main():
  parser = argparse.ArgumentParser(description="Takes in qteeConfigInfo\
                   parameters and encodes a string to be used in the device tree.")
  parser.add_argument("-p", "--permissions",help="Path to JSON containing permissions \
                      for each VM. Please see VMQteeConfigInfoPerms.json for details.",
                      dest="perms", required=True, type=lambda x: is_file_valid(parser, x))
  args = parser.parse_args()
  print("Please replace the qtee-config-info node in the device tree with the following:\n")
  perms_for_each_vm_dict = generate_cclent_env_perms(args.perms, idl_mapping)
  for vm_perm in perms_for_each_vm_dict:
    print("Perms for " + str(vm_perm) + "\n")
    print("qcom,qtee-config-info = " + str(perms_for_each_vm_dict[vm_perm]) + "\n")


if __name__ == '__main__':
  main()