#===============================================================================
#
# App Core
#
# GENERAL DESCRIPTION
#    build script
#
#
#-------------------------------------------------------------------------------
#
#  $Header:  $
#  $DateTime: $
#  $Author: $
#  $Change: $
#                      EDIT HISTORY FOR FILE
#
#  This section contains schedulerents describing changes made to the module.
#  Notice that changes are listed in reverse chronological order.
#===============================================================================
Import('env')
env = env.Clone()
import os
import os.path
import string

# Adding entry for current TA in external build sanity script which tests
# compilation of TAs in external build.
try:
  # Fetch the path of current Sconscript file.
  this_sconscript = (lambda x:x).__code__.co_filename
  env.ExtSdkBldSanity(this_sconscript)
except:
  pass

# Set this flag to true if tha current TA is chipset independent and doesn't 
# require to be rebuilt for every chipset.
env['CHIPSET_INDEPENDENT'] = True

#-------------------------------------------------------------------------------
# Build Target
#-------------------------------------------------------------------------------
target_name = "prov"

#env.Append(OUT_DIR = QSEE_APP_DIR + '/bsp/trustzone/qsapps/' + target_name + '/build')
env['APP_NAME'] = target_name

if env.get('CHIPSET_INDEPENDENT'):
    env['OUT_DIR'] = os.path.join(env['BUILD_ROOT'], 'apps/bsp/trustzone/qsapps/${APP_NAME}/build/') 

#-------------------------------------------------------------------------------
# PROV Feature Tags
#-------------------------------------------------------------------------------
LLVM_CHIPSETS = ['msm8937', 'msm8953', 'msm8996', 'msm8998', 'sdm660', 'sdm670', 'sdm845', 'sdm855', 'sm6150', 'sm7150', 'sdm439', 'sm8250','sm7250', 'saipan', 'sm8350', 'lahaina', 'sm7125', 'rennell', 'sm7225', 'bitra', 'sm7325', 'kodiak', 'waipio', 'divar']
STACK_HEAP_IN_APP_METADATA_CHIPSETS = ['sdm670', 'sdm845', 'sdm855', 'sm6150', 'sm7150', 'sm8250','sm7250', 'saipan', 'sm8350', 'lahaina', 'sm7125', 'rennell', 'sm7225', 'bitra', 'sm7325', 'kodiak', 'waipio', 'divar']

DEVELOPER_LOCAL_BUILD = os.environ.get('DEVELOPER_LOCAL_BUILD')

BUILD_TOOL = "llvm" if env['CHIPSET'] in LLVM_CHIPSETS else "arm"
if env['CHIPSET'] == 'msm8952' or env['CHIPSET'] == 'msm8956':
  if os.environ.get('LLVMTOOLS') == 'LLVM':
    BUILD_TOOL = 'llvm'

SET_STACK_HEAP_IN_APP_METADATA = "True" if env['CHIPSET'] in STACK_HEAP_IN_APP_METADATA_CHIPSETS else "False"
USE_SECURE_APP_BUILDER = "True" if hasattr(env, 'SecureAppBuilder') \
                          and env['CHIPSET'] != "msm8937" \
                          else "False"

ENABLE_NEW_TA_BUILD = "False"
if os.environ.get('SUPPORT_NEW_TA_BUILD') == 'true' :
    ENABLE_NEW_TA_BUILD = "True"

if DEVELOPER_LOCAL_BUILD == "True":
    BUILD_MODE = os.getenv("MODE", "RELEASE").upper()
    assert BUILD_MODE in ["RELEASE", "DEBUG"]
    OS_TYPE = os.environ["OS_TYPE"].upper()
    PROC = "A53_64" if os.getenv("MACH_SWD", "") == "64" else "scorpion"
    USE_SCRYPTO = os.environ["USE_SCRYPTO"]
else:
    BUILD_MODE = "RELEASE"
    OS_TYPE = "ANDROID"
    USE_SCRYPTO = "False"
    if env['PROC'] == 'scorpion':
        ARCH_SUFFIX = ""
    else:
        ARCH_SUFFIX = "_64"

DRK_TARGET_BUILD_VARIANT =  "none"
if os.environ.get('TARGET_BUILD_VARIANT') == 'eng' :
    DRK_TARGET_BUILD_VARIANT = "eng"

SYSTEM_HIDL_ENABLED = "True"
QSEE_APP_DIR = env['BUILD_ROOT'] + '/apps'

COMMON_CPPDEFINES = [
   "USE_QSEE",
   BUILD_MODE,
   "USE_%s" % OS_TYPE,
   "BUILD_BOOT_CHAIN",
   "BUILD_BOOT_CHAIN_SPBL",
   "BOOT_LOADER",
   "BOOT_WATCHDOG_DISABLED",
   "FLASH_NAND_SINGLE_THREADED",
   "FLASH_CLIENT_BOOT",
   "FLASH_USE_DM_PAGES",
   "FEATURE_HS_USB_BASIC",
   "BOOT_SBL_H=\\\"boot_comdef.h\\\"",
   "BOOT_CUSTSBL_H=\\\"custsbl.h\\\"",
   "BOOT_MODULE_BUILD_VERSION=" + env['BUILD_VER'],
   "FEATURE_USES_TURBO",
   "RUMIBUILD",
]

env.Replace(SRC_DIR = QSEE_APP_DIR+'/securemsm/trustzone/qsapps/' + target_name + '/src')
env.Replace(LIB_DIR = QSEE_APP_DIR+'/securemsm/trustzone/qsapps/' + target_name + '/lib')
env.Replace(INC_DIR = QSEE_APP_DIR+'/securemsm/trustzone/qsapps/' + target_name + '/include')
env.Replace(TARGET_NAME = target_name)

#-------------------------------------------------------------------------------
# Compiler, object, and linker definitions
#-------------------------------------------------------------------------------

if BUILD_TOOL == "llvm":
  env.Append(CFLAGS = " -fPIC") # ' --apcs=/ropi/rwpi --lower_ropi --lower_rwpi')
  env.Append(CCFLAGS = " -fstack-protector")
  env.Append(CFLAGS = " -Werror")
  # Apply stack protection - requested by yj0729.kim at 17.12.05.
  env.Append(CFLAGS = ' -fstack-protector -fstack-protector-all')
#------------------------------------------------------------------------------
# We need to specify "neon" to generate SIMD instructions in 32-bit mode
#------------------------------------------------------------------------------
  if env['PROC'] == 'scorpion':
    env.Append(CCFLAGS = " -mfpu=neon ")
elif BUILD_TOOL =="arm":
  env.Append(CCFLAGS = " --gnu --c99 --no_vla")
  env.Append(CCFLAGS = " --protect_stack ")
  env.Append(CFLAGS = ' --apcs=/ropi/rwpi --lower_ropi --lower_rwpi')
  env.Append(ASFLAGS = ' --apcs=/ropi/rwpi ')
  # do not generate thumb code for inline assembler code
  env.Append(ARMCC_OPT = ' --arm')
  # Suppress Error: C9933W: Waiting for license...
  env.Append(ARMCC_OPT = ' --licretry --diag_suppress=9931,9933 --diag_remark=9933')
  # Apply stack protection - requested by yj0729.kim at 17.12.05.
  env.Append(CFLAGS = ' --protect_stack --protect-stack-all')

env.Append(CPPDEFINES = COMMON_CPPDEFINES)

APP_INCLUDES = [
    "${INC_DIR}/",
    "${INC_DIR}/common/",
    "${INC_DIR}/crypto/",
    "${INC_DIR}/crypto/x509/",
    "${INC_DIR}/prov/",
    "${INC_DIR}/prov/qsee/",
    "${INC_DIR}/skmShared/",
    "${INC_DIR}/logEncryptor",
    env['BUILD_ROOT'] + '/core/api/services',
    QSEE_APP_DIR+'/api/securemsm/trustzone/qsee',
]

#----------------------------------------------------------------------------
# App core Objects
#----------------------------------------------------------------------------
APP_CORE_ENTRY_SOURCES = [
    '${SRC_DIR}/prov/certRevocationList.c',
    '${SRC_DIR}/prov/cryptoPlatform.c',
    '${SRC_DIR}/prov/keyManager.c',
    '${SRC_DIR}/prov/log.c',
    '${SRC_DIR}/prov/teeCmdExecuter.c',
    '${SRC_DIR}/prov/qsee/qseeAppMain.c',
    '${SRC_DIR}/prov/qsee/qseeCryptoApi.c',
    '${SRC_DIR}/prov/qsee/qseeSecureState.c',
    '${SRC_DIR}/crypto/cryptoEngine.c',
    '${SRC_DIR}/crypto/secMemoryManager.c',
    '${SRC_DIR}/crypto/x509/asn1build.c',
    '${SRC_DIR}/crypto/x509/asn1build_ec.c',
    '${SRC_DIR}/crypto/x509/asn1build_rsa.c',
    '${SRC_DIR}/crypto/x509/asn1.c',
    '${SRC_DIR}/crypto/x509/asn1ec.c',
    '${SRC_DIR}/crypto/x509/asn1gen.c',
    '${SRC_DIR}/crypto/x509/asn1rsa.c',
    '${SRC_DIR}/crypto/x509/certGenerator.c',
    '${SRC_DIR}/crypto/x509/certParser.c',
    '${SRC_DIR}/crypto/x509/x509v3.c',
    '${SRC_DIR}/common/taConfig.c',
    '${SRC_DIR}/common/TLV.c',
    '${SRC_DIR}/logEncryptor/circularQueue.c',
    '${SRC_DIR}/logEncryptor/logEncryptor.c',
]

arm_libs = []
#-------------------------------------------------------------------------------
# SDS White box configuration for DRK v2 / SAK / GAK.
#-------------------------------------------------------------------------------
if os.path.isdir('../src/SWBCLibrary_src'):
    print ('[DeviceRootKey] Using SWBC sources...')
    APP_INCLUDES += [ "${SRC_DIR}/SWBCLibrary_src/include", ]
    APP_CORE_ENTRY_SOURCES += [
        '${SRC_DIR}/SWBCLibrary_src/swbc_prov.c',
        '${SRC_DIR}/SWBCLibrary_src/swbc_prov_table.c',
        '${SRC_DIR}/SWBCLibrary_src/src/aes128-swbc-layer1-cbc.c',
        '${SRC_DIR}/SWBCLibrary_src/src/swbc-aes.c',
        '${SRC_DIR}/SWBCLibrary_src/src/swbc-utils.c',
    ]
else:
    print ('[DeviceRootKey] Using SWBC library...')
    if BUILD_TOOL == "llvm":
        arm_libs.append(env.File(env.SubstRealPath("${LIB_DIR}/wb/sds/swb_prov_llvm%s.lib" % ARCH_SUFFIX)))
    else:
        arm_libs.append(env.File(env.SubstRealPath("${LIB_DIR}/wb/sds/swb_prov_rvct5.lib")))

# crypto platform definitions
if USE_SCRYPTO == "True":
    env.Append( ARMCC_OPT = ' -DUSE_SCRYPTO')
    env.Append( ARMCC_OPT = ' -DOPENSSL_FIPS')
    APP_INCLUDES += [
      "${INCLUDEPATH}/../scrypto_qc/fips/include/openssl",
      "${INCLUDEPATH}/common/include/scrypto",
      "${INCLUDEPATH}/common/src/scrypto/openssl",
      "${INCLUDEPATH}/common/src/scrypto",
    ]
    APP_CORE_ENTRY_SOURCES += [
        "${SRC_DIR}/common/src/crypto/crypto_core/rsa.c",
        "${SRC_DIR}/common/src/crypto/crypto_core/ec.c",
        "${SRC_DIR}/scrypto_qc/fips/lib/fips_premain.c",
        "${SRC_DIR}/scrypto_qc/fips/lib/fips_static_hmac.c",
    ]
    # crypto platform static lib
    cc_static_lib = [
        "${COMMON_DIR}/lib/qc_scrypto/env['CHIPSET'].lib",
    ]
else:
    # Openssl Mini.
    APP_INCLUDES += [ "${INC_DIR}/crypto/openssl", ]
    APP_CORE_ENTRY_SOURCES += [
        '${SRC_DIR}/crypto/openssl_mini/ex_data.c',
        '${SRC_DIR}/crypto/openssl_mini/mem_clr.c',
        '${SRC_DIR}/crypto/openssl_mini/memmgrs.c',
        '${SRC_DIR}/crypto/openssl_mini/aes/aes_core.c',
        '${SRC_DIR}/crypto/openssl_mini/aes/aes_gcm.c',
        '${SRC_DIR}/crypto/openssl_mini/aes/gcm128.c',
        '${SRC_DIR}/crypto/openssl_mini/asn1/a_int.c',
        '${SRC_DIR}/crypto/openssl_mini/asn1/a_bitstr.c',
        '${SRC_DIR}/crypto/openssl_mini/asn1/asn1_lib.c',
        '${SRC_DIR}/crypto/openssl_mini/asn1/a_type.c',
        '${SRC_DIR}/crypto/openssl_mini/asn1/tasn_dec.c',
        '${SRC_DIR}/crypto/openssl_mini/asn1/tasn_enc.c',
        '${SRC_DIR}/crypto/openssl_mini/asn1/tasn_fre.c',
        '${SRC_DIR}/crypto/openssl_mini/asn1/tasn_new.c',
        '${SRC_DIR}/crypto/openssl_mini/asn1/tasn_typ.c',
        '${SRC_DIR}/crypto/openssl_mini/asn1/tasn_utl.c',
        '${SRC_DIR}/crypto/openssl_mini/asn1/x_bignum.c',
        '${SRC_DIR}/crypto/openssl_mini/bn/bn_add.c',
        '${SRC_DIR}/crypto/openssl_mini/bn/bn_asm.c',
        '${SRC_DIR}/crypto/openssl_mini/bn/bn_ctx.c',
        '${SRC_DIR}/crypto/openssl_mini/bn/bn_div.c',
        '${SRC_DIR}/crypto/openssl_mini/bn/bn_gcd.c',
        '${SRC_DIR}/crypto/openssl_mini/bn/bn_exp.c',
        '${SRC_DIR}/crypto/openssl_mini/bn/bn_kron.c',
        '${SRC_DIR}/crypto/openssl_mini/bn/bn_lib.c',
        '${SRC_DIR}/crypto/openssl_mini/bn/bn_mod.c',
        '${SRC_DIR}/crypto/openssl_mini/bn/bn_mont.c',
        '${SRC_DIR}/crypto/openssl_mini/bn/bn_mul.c',
        '${SRC_DIR}/crypto/openssl_mini/bn/bn_prime.c',
        '${SRC_DIR}/crypto/openssl_mini/bn/bn_rand.c',
        '${SRC_DIR}/crypto/openssl_mini/bn/bn_recp.c',
        '${SRC_DIR}/crypto/openssl_mini/bn/bn_shift.c',
        '${SRC_DIR}/crypto/openssl_mini/bn/bn_sqr.c',
        '${SRC_DIR}/crypto/openssl_mini/bn/bn_sqrt.c',
        '${SRC_DIR}/crypto/openssl_mini/bn/bn_word.c',
        '${SRC_DIR}/crypto/openssl_mini/ec/ec.c',
        '${SRC_DIR}/crypto/openssl_mini/ec/ec_curve.c',
        '${SRC_DIR}/crypto/openssl_mini/ec/ec_cvt.c',
        '${SRC_DIR}/crypto/openssl_mini/ec/ec_key.c',
        '${SRC_DIR}/crypto/openssl_mini/ec/ec_lib.c',
        '${SRC_DIR}/crypto/openssl_mini/ec/ec_mult.c',
        '${SRC_DIR}/crypto/openssl_mini/ec/ec_oct.c',
        '${SRC_DIR}/crypto/openssl_mini/ec/ecp_mont.c',
        '${SRC_DIR}/crypto/openssl_mini/ec/ecp_oct.c',
        '${SRC_DIR}/crypto/openssl_mini/ec/ecp_smpl.c',
        '${SRC_DIR}/crypto/openssl_mini/ecdsa/ecs_asn1.c',
        '${SRC_DIR}/crypto/openssl_mini/ecdsa/ecs_lib.c',
        '${SRC_DIR}/crypto/openssl_mini/ecdsa/ecs_ossl.c',
        '${SRC_DIR}/crypto/openssl_mini/ecdsa/ecs_sign.c',
        '${SRC_DIR}/crypto/openssl_mini/ecdsa/ecs_vrf.c',
        '${SRC_DIR}/crypto/openssl_mini/lhash/lhash.c',
        '${SRC_DIR}/crypto/openssl_mini/rsa/rsa.c',
        '${SRC_DIR}/crypto/openssl_mini/rsa/rsa_lib.c',
        '${SRC_DIR}/crypto/openssl_mini/rsa/rsa_gen.c',
        '${SRC_DIR}/crypto/openssl_mini/stack/stack.c',
    ]

#-------------------------------------------------------------------------------
# Add definitions
#-------------------------------------------------------------------------------
if SYSTEM_HIDL_ENABLED == "True":
    env.Append( ARMCC_OPT = ' -DSYSTEM_ROOT_IMAGE_ENABLED')

if DRK_TARGET_BUILD_VARIANT == "eng":
    env.Append( ARMCC_OPT = ' -DDRK_TEST_API_ENABLED')

#-------------------------------------------------------------------------------
# Add metadata to image
#-------------------------------------------------------------------------------

if ENABLE_NEW_TA_BUILD == "False" :
    md = {
           'appName':    target_name,
           'privileges': ['default',
                          'OEMUnwrapKeys',
                          'CertValidate',
                         ],
        }
else :
    md = {
           'appName':    target_name,
           'privileges': ['default',
                          'OEMUnwrapKeys',
                          'CertValidate',
                          'System',
                         ],
        }    

if SET_STACK_HEAP_IN_APP_METADATA == "True":
    md['heapSize'] = 0x40000
    md['stackSize'] = 0x40000

print("[DeviceRootKey] ENABLE_NEW_TA_BUILD FOR PROV : " + str(ENABLE_NEW_TA_BUILD))
if ENABLE_NEW_TA_BUILD == "True":
    env.Append(LINKFLAGS=' -no-threads ') # Added to build TA in deterministic way in order to reduce the cost of duplicated signing

if USE_SECURE_APP_BUILDER == "True":
    if env["PROC"] == "scorpion":
        arm_libs.append(File(env.SubstRealPath('${MUSL32PATH}/lib/libc.a')))
    else:
        arm_libs.append(File(env.SubstRealPath('${MUSLPATH}/lib/libc.a')))

    if SET_STACK_HEAP_IN_APP_METADATA == "True":
        prov_units = env.SecureAppBuilder(
          sources = APP_CORE_ENTRY_SOURCES,
          includes = APP_INCLUDES,
          metadata = md,
          image = target_name,
          user_libs = arm_libs,
        )
    else:
        prov_units = env.SecureAppBuilder(
          sources = APP_CORE_ENTRY_SOURCES,
          includes = APP_INCLUDES,
          metadata = md,
          image = target_name,
          user_libs = arm_libs,
          stack_size = '0x40000',
          heap_size = '0x40000',
        )

    if hasattr(env, 'IMAGE_ALIASES'):
        for image in env['IMAGE_ALIASES']:
            op = env.Alias(image, prov_units)
    else:
        env.Alias(target_name, prov_units)

    Return('prov_units')