# ************************************************************************************************
# Environment

INFO_TITLE ?= Trusted Application Build
$(info ******************************************)
$(info $(INFO_TITLE))
$(info ******************************************)

# PLATFORM : ARM_V7A_STD
ifeq ($(PLATFORM),)
$(info - PLATFORM  is  not  set,  default  is : ARM_V7A_STD)
PLATFORM := ARM_V7A_STD
endif

# MODE : Debug, Release
ifeq ($(MODE),)
$(info - MODE  is  not  set,  default  is : Debug)
MODE := Debug
endif

# TOOLCHAIN : GNU, ARM
ifeq ($(TOOLCHAIN),)
$(info - TOOLCHAIN is not set, default is : GNU)
# Samsung change : Use ARM compileer by default
TOOLCHAIN := ARM
endif

# GP ENTRY : tlMain, GP Entrypoints
ifeq ($(GP_ENTRYPOINTS),)
$(info - GP_ENTRYPOINTS is not set, default is : N)
GP_ENTRYPOINTS := N
endif

# TA_INTERFACE_VERSION : major.minor
ifeq ($(TA_INTERFACE_VERSION),)
$(info - TA_INTERFACE_VERSION  is  not  set,  default  is : 0.0)
TA_INTERFACE_VERSION := 0.0
endif

# TBASE_API_LEVEL
TBASE_API_LEVEL_TOP := 11
ifeq ($(TBASE_API_LEVEL),)
$(info - TBASE_API_LEVEL  is  not  set,  default  is : $(TBASE_API_LEVEL_TOP))
TBASE_API_LEVEL := $(TBASE_API_LEVEL_TOP)
endif

# HW_FLOATING_POINT
ifeq ($(HW_FLOATING_POINT),)
$(info - HW_FLOATING_POINT  is  not  set,  default  is : N)
HW_FLOATING_POINT := N
endif

# TA_ROLLBACK_PROTECTED
ifeq ($(TA_ROLLBACK_PROTECTED),)
$(info - TA_ROLLBACK_PROTECTED  is  not  set,  default  is : N)
TA_ROLLBACK_PROTECTED := N
endif

# TA_SERVICE_TYPE
TA_SERVICE_TYPE ?= $(TRUSTLET_SERVICE_TYPE)
ifeq ($(TA_SERVICE_TYPE),)
TA_SERVICE_TYPE := SYS
endif

# TA_PIE
TA_PIE ?= PIE
ifeq ($(TOOLCHAIN), ARM)
   TA_PIE := NON_PIE
   $(warning "ASLR feature not activated: TOOLCHAIN is ARM")
endif
ifeq ($(shell test $(TBASE_API_LEVEL) -lt 5; echo $$?),0)
   TA_PIE := NON_PIE
   $(warning "ASLR feature not activated: TBASE_API_LEVEL is less than 5")
endif

GP_LIBRARY ?= Standard

$(info ******************************************)
$(info MODE                 : $(MODE))
$(info TOOLCHAIN            : $(TOOLCHAIN))
$(info PLATFORM             : $(PLATFORM))
$(info INTERFACE_VERSION    : $(TA_INTERFACE_VERSION))
$(info TBASE_API_LEVEL      : $(TBASE_API_LEVEL))
$(info HW_FLOATING_POINT    : $(HW_FLOATING_POINT))
$(info ROLLBACK_PROTECTED   : $(TA_ROLLBACK_PROTECTED))
$(info GP-ENTRIES           : $(GP_ENTRYPOINTS))
$(info GP_LIBRARY           : $(GP_LIBRARY))
$(info TA_SERVICE_TYPE      : $(TA_SERVICE_TYPE))
$(info ******************************************)

# Check if variables are correctly set
ifneq ($(MODE),Debug)
   ifneq ($(MODE),Release)
      $(error ERROR : MODE value is not correct : $(MODE))
   endif
endif
ifeq ($(filter $(TOOLCHAIN),GNU ARM CLANG),)
$(error ERROR : TOOLCHAIN value is not correct : $(TOOLCHAIN))
endif
ifneq ($(GP_ENTRYPOINTS),N)
   ifneq ($(GP_ENTRYPOINTS),Y)
      $(error ERROR : GP_ENTRYPOINTS value is not correct : $(GP))
   endif
endif
define N


endef
ifneq ($(TBASE_API_LEVEL),$(TBASE_API_LEVEL_TOP))
   $(warning $(N)\
   $(N)\
   ******************************************$(N)\
   WARNING : makefile sets TBASE_API_LEVEL to $(TBASE_API_LEVEL) which is lower than $(TBASE_API_LEVEL_TOP)$(N)\
   Trustonic recommends to not define this variable and use the default value for maximum security$(N)\
   ******************************************$(N))
endif
ifneq ($(HW_FLOATING_POINT),N)
   ifneq ($(HW_FLOATING_POINT),Y)
      $(error ERROR : HW_FLOATING_POINT value is not correct : $(HW_FLOATING_POINT))
   endif
endif
ifneq ($(TA_ROLLBACK_PROTECTED),N)
   ifneq ($(TA_ROLLBACK_PROTECTED),Y)
      $(error ERROR : TA_ROLLBACK_PROTECTED value is not correct : $(TA_ROLLBACK_PROTECTED))
   endif
endif


# Accept old variable names
TRUSTED_APP_DIR ?= $(TRUSTLET_DIR)

TA_UUID ?= $(TRUSTLET_UUID)
TA_UUID := $(shell echo $(TA_UUID) | tr A-Z a-z)
TA_MEMTYPE ?= $(TRUSTLET_MEMTYPE)
TA_KEYFILE ?= $(TRUSTLET_KEYFILE)
TA_FLAGS ?= $(TRUSTLET_FLAGS)

# Default values for mostly irrelevant properties
ifeq ($(TA_MEMTYPE),)
TA_MEMTYPE := 2  # 0: internal memory prefered; 1: internal memory used; 2: external memory used
endif

# Convenience values for SERVICE_TYPE
ifneq ($(strip $(TA_SERVICE_TYPE)),1)
   ifneq ($(strip $(TA_SERVICE_TYPE)),2)
      ifneq ($(strip $(TA_SERVICE_TYPE)),3)
         ifneq ($(strip $(TA_SERVICE_TYPE)),4)
            ifneq ($(strip $(TA_SERVICE_TYPE)),SP)
               ifneq ($(strip $(TA_SERVICE_TYPE)),SYS)
                  $(error ERROR : TA_SERVICE_TYPE value is not correct : -$(TA_SERVICE_TYPE)-)
                  endif
               endif
            endif
      endif
   endif
endif
ifeq ($(strip $(TA_SERVICE_TYPE)),SP)
TA_SERVICE_TYPE := 2
endif
ifeq ($(strip $(TA_SERVICE_TYPE)),SYS)
TA_SERVICE_TYPE := 3
endif

# Default values for mostly irrelevant properties
ifeq ($(TA_FLAGS),)
TA_FLAGS := 0 # 0: no flag; 1: permanent; 2: service has no WSM control interface; 4: debuggable
endif
ifeq ($(TA_DEBUGGABLE),Y)
TA_FLAGS := $$(($(TA_FLAGS)|4))
endif

DOWNGRADE_PROTECTED :=
ifeq ($(TA_ROLLBACK_PROTECTED),Y)
   DOWNGRADE_PROTECTED := --downgrade-protected
endif

# Extended memory layout support is by default for TBASE_API_LEVEL>=5
EXTENDED_LAYOUT = $(shell if [ $(TBASE_API_LEVEL) -ge 5 ] ; then echo Y ; else echo NO ; fi)
TA_HEAP_SIZE_INIT_PARAM :=
TA_HEAP_SIZE_MAX_PARAM :=
ifeq ($(call EXTENDED_LAYOUT),Y)
    TA_FLAGS := $$(($(TA_FLAGS)|8))
    ifneq ($(HEAP_SIZE_INIT),)
        TA_HEAP_SIZE_INIT_PARAM :=  -initheapsize $(HEAP_SIZE_INIT)
        ifeq ($(HEAP_SIZE_MAX),)
            TA_HEAP_SIZE_MAX_PARAM :=  -maxheapsize $(HEAP_SIZE_INIT)
        else
            TA_HEAP_SIZE_MAX_PARAM :=  -maxheapsize $(HEAP_SIZE_MAX)
        endif
    endif
else
    ifeq ($(HW_FLOATING_POINT),Y)
        $(error ERROR : require TBASE_API_LEVEL >= 5 to enable HW_FLOATING_POINT)
    endif
endif

# Default values for mostly irrelevant properties
TA_INSTANCES ?= $(TRUSTLET_INSTANCES)
ifeq ($(TA_INSTANCES),)
TA_INSTANCES := 16 # min: 1; max: 16
endif

TA_ADD_FLAGS ?= $(TRUSTLET_ADD_FLAGS)

TA_OPTS ?= $(TRUSTLET_OPTS)

TASDK_DIR ?= $(TLSDK_DIR)
TASDK_DIR_SRC ?= $(TLSDK_DIR_SRC)

GPENTRY_LIB :=
GP_LEVEL :=
GP_UUIDKEYFILE :=

GPTRIC_ROOT ?= ${components_folder}/Crypt/Out/Bin/$(MODE)

ifeq ($(GP_LIBRARY),Standard)
    GPAPI_LIB := $(TASDK_DIR_SRC)/Bin/GpApi/$(TA_PIE)/GpApi.lib
else ifeq ($(GP_LIBRARY),GpTRIC)
    GPAPI_LIB := $(GPTRIC_ROOT)/GpTRIC.lib
else
    $(error ERROR : GP_LIBRARY value not recognized. Currently : $(GP_LIBRARY))
endif

ifeq ($(GP_ENTRYPOINTS),Y)
    GPENTRY_LIB := $(TASDK_DIR_SRC)/Bin/GpEntry/$(TA_PIE)/GpEntry.lib
    GP_LEVEL := -gp_level GP
    ifeq ($(TA_SERVICE_TYPE),2)
    	ifeq ("$(wildcard $(TA_UUIDKEYFILE))","")
            $(error ERROR : TA_UUIDKEYFILE has to be set correctly for GP-SPTAs. Currently : $(TA_UUIDKEYFILE))
        endif
        GP_UUIDKEYFILE := -uuidkeyfile $(TA_UUIDKEYFILE)
        GP_UUID  := $(shell java -jar $(TASDK_DIR_SRC)/Bin/MobiConvert/MobiConvert.jar $(GP_UUIDKEYFILE) --printuuid | tr -d '-')
    else
        GP_UUID  := $(TA_UUID)
    endif
    $(info GP_UUID              : $(GP_UUID))
endif
# Toolchain set up
ifeq ($(TOOLCHAIN),GNU)
   LINKER_SCRIPT=$(TASDK_DIR_SRC)/trusted_application.ld

   CC=$(CROSS_GCC_PATH_BIN)gcc
   LINKER=$(CC)
   READELF=$(CROSS_GCC_PATH_BIN)readelf
   OBJDUMP=$(CROSS_GCC_PATH_BIN)objdump
   #ASM=$(CROSS_GCC_PATH_BIN)as
   #We use gcc as preprocessor for GNU asm
   ASM=$(CROSS_GCC_PATH_BIN)gcc
   ARCH=$(CROSS_GCC_PATH_BIN)ar
else ifeq ($(TOOLCHAIN),CLANG)
   LINKER_SCRIPT=$(TASDK_DIR_SRC)/trusted_application.ld

   CC=$(COMP_PATH_CLANG)/bin/clang -I $(CROSS_GCC_PATH)/arm-eabi/libc/usr/include
   LINKER=$(COMP_PATH_CLANG)/bin/clang -L $(CROSS_GCC_PATH)/arm-eabi/libc/usr/lib/v7-a
   READELF=$(COMP_PATH_CLANG)/bin/llvm-readelf
   OBJDUMP=$(COMP_PATH_CLANG)/bin/llvm-objdump
   #ASM=llvm-as
   #We use clang as preprocessor for CLANG asm
   ASM=$(CC)
   ARCH=$(COMP_PATH_CLANG)/bin/llvm-ar
else
   LINKER_SCRIPT=$(TASDK_DIR_SRC)/trusted_application.sct

   CC=$(ARM_RVCT_PATH_BIN)/armcc
   ASM=$(ARM_RVCT_PATH_BIN)/armasm
   LINKER=$(ARM_RVCT_PATH_BIN)/armlink
   READELF=$(ARM_RVCT_PATH_BIN)/fromelf
   ARCH=$(ARM_RVCT_PATH_BIN)/armar
endif

# OUTPUT_ROOT used to clean build, keep it defined
OUTPUT_ROOT := $(TRUSTED_APP_DIR)/../../Out/Bin

# TODO remove that when TAs will be platform dependent (64 bit TAs)
PLATFORM_OUT :=
ifeq ($(strip $(TA_SERVICE_TYPE)),1)
   PLATFORM_OUT := $(PLATFORM)
endif

ifneq ($(filter $(TOOLCHAIN),GNU CLANG),)
#   OUTPUT_PATH ?= $(OUTPUT_ROOT)/$(TOOLCHAIN)/$(MODE)
#   OUTPUT_PATH_INDEPENDENT := $(OUTPUT_ROOT)/$(TOOLCHAIN)
   OUTPUT_PATH ?= $(OUTPUT_ROOT)/$(MODE)
   OUTPUT_PATH_INDEPENDENT := $(OUTPUT_ROOT)/$(MODE)
else
   OUTPUT_PATH ?= $(OUTPUT_ROOT)/$(MODE)
   OUTPUT_PATH_INDEPENDENT := $(OUTPUT_ROOT)
endif

OUTPUT_OBJ_PATH=$(OUTPUT_PATH)/obj-local

# ************************************************************************************************
# Trusted application being built
TA_AXF := $(OUTPUT_PATH)/$(OUTPUT_NAME).axf
TA_LST2 := $(OUTPUT_PATH)/$(OUTPUT_NAME).lst2
TA_LIB := $(OUTPUT_PATH_INDEPENDENT)/$(OUTPUT_NAME).lib
ifeq ($(GP_ENTRYPOINTS),Y)
TA_BIN := $(OUTPUT_PATH)/$(TA_UUID).tabin
GP_BIN := $(OUTPUT_PATH)/$(GP_UUID).tabin
TA_LOG_FILE_NAME=$(OUTPUT_PATH)/$(OUTPUT_NAME)_$(GP_UUID).tabin.log
ENCRYPTED_TA_LOG_FILE_NAME=$(OUTPUT_PATH)/$(OUTPUT_NAME)_$(GP_UUID).tabin.log.encrypted
else
TA_BIN := $(OUTPUT_PATH)/$(TA_UUID).tlbin
TA_LOG_FILE_NAME=$(OUTPUT_PATH)/$(OUTPUT_NAME)_$(TA_UUID).tlbin.log
ENCRYPTED_TA_LOG_FILE_NAME=$(OUTPUT_PATH)/$(OUTPUT_NAME)_$(TA_UUID).tlbin.log.encrypted
endif
UUID_H := $(OUTPUT_ROOT)/../Public/$(OUTPUT_NAME)_uuid.h

ifeq ($(GP_ENTRYPOINTS),Y)
	GP_TA_CONFIG_FILE ?=
ifneq ($(GP_TA_CONFIG_FILE),)
	GP_TA_PROP_PARAM := --gp_prop write $(TA_AXF) $(GP_TA_CONFIG_FILE)
endif
endif

# ************************************************************************************************
# TASDK
TASDK_SRC_C :=
TASDK_SRC_ASM :=
TASDK_DIR_INC := \
    $(TASDK_DIR_SRC)/Public \
    $(TASDK_DIR_SRC)/Public/MobiCore/inc \
    $(TASDK_DIR_SRC)/Public/GPD_TEE_Internal_API
TLAPI_LIB := $(TASDK_DIR_SRC)/Bin/TlApi/$(TA_PIE)/TlApi.lib
TLENTRY_LIB := $(TASDK_DIR_SRC)/Bin/TlEntry/$(TA_PIE)/TlEntry.lib

# ************************************************************************************************
# ************************************************************************************************
# ************************************************************************************************
# Architecture specifics
ifeq ($(PLATFORM_MAKEFILES),)
    ARM_ARCH := ARMv7
    ARM_CHIP := ARMV7_A
    ARM_SHAPE := STD
    ARM_CPU := generic-armv7-a
    ARM_FPU := vfp
    ARM_FLOAT_ABI := soft
else
   include $(PLATFORM_MAKEFILES)
endif
ARM_PLAT := $(ARM_CHIP)_$(ARM_SHAPE)

# Toolchain options
STD_LIBS ?=
ARM_OPT_CC :=
TARGET :=
TARGET_LIB :=
TRIPLE := thumbv7a-none-eabi
ifneq ($(filter $(TOOLCHAIN),GNU CLANG),)
    ifeq ($(TOOLCHAIN),CLANG)
        TARGET += --target=$(TRIPLE)
    endif
    ifeq ($(ARM_CPU),generic-armv7-a)
        TARGET += -march=armv7-a
    else
        TARGET += -mcpu=$(ARM_CPU)
    endif

    ifeq ($(HW_FLOATING_POINT),Y)
        TARGET += -mfpu=neon-vfpv4
        TARGET += -mfloat-abi=softfp
    else
        TARGET += -mfpu=$(ARM_FPU)
        TARGET += -mfloat-abi=$(ARM_FLOAT_ABI)
    endif

    ifeq ($(TOOLCHAIN),CLANG)
        TARGET_LIB += --target=$(TRIPLE)
    else
        TARGET_LIB += -march=armv7-a
    endif

    STD_LIBS += -lm -lc -lgcc

    #ARM_OPT_CC += -Werror
    ARM_OPT_CC += -Wall
    ARM_OPT_CC += -Wextra
	#ARM_OPT_CC += -U__INT32_TYPE__ -U__UINT32_TYPE__  -D__INT32_TYPE__="int"
else
    ifeq ($(HW_FLOATING_POINT),Y)
        TARGET += --cpu=cortex-a15
        TARGET += --fpu=VFPv4
    else
        TARGET += --cpu=7-A
        TARGET += --fpu=SoftVFP
    endif
    TARGET_LIB += --cpu=7-A
    TARGET_LIB += --fpu=SoftVFP

    ARM_OPT_LINK := $(TARGET) # copy cpu/fpu settings

    # Special treatment for --diag_error=warnings, downgrade compiler warnings to remarks
    # Suppress Error: C9931W: Your license for Compiler (feature compiler) will expire in 28 days
    ARM_OPT_CC += --diag_remark=9931
    # Suppress Error: C9933W: Waiting for license...
    ARM_OPT_CC += --diag_remark=9933
    # Treat "#223-D: function declared implicitly" as an error
    ARM_OPT_CC += --diag_error=223
    # Suppress Error:  #1215-D: #warning directive
    ARM_OPT_CC += --diag_remark=1215

#   ARM_OPT_CC += --diag_error=warning
    ARM_OPT_CC += --remarks
    ARM_OPT_CC += --brief_diagnostics
endif

ARM_OPT_CC += -DPLAT=$(ARM_PLAT)
ARM_OPT_CC += -DARM_ARCH=$(ARM_ARCH) -D__$(ARM_ARCH)__
ARM_OPT_CC += -D__$(ARM_CHIP)__
ARM_OPT_CC += -D__$(ARM_PLAT)__
ARM_OPT_CC += $(TA_OPTS)
ARM_OPT_CC += -DTBASE_API_LEVEL=$(TBASE_API_LEVEL)

ARM_OPT_CC += -U__INT32_TYPE__ -U__UINT32_TYPE__  -D__INT32_TYPE__="int"  -D__UINT32_TYPE__="unsigned int"

# setup SSP (Stack Smashing Protection)
ifeq ($(TOOLCHAIN),GNU)
    # enable Stack Smashing Protection in GCC
    # starting from GCC 4.9 a new flag fstack-protector-strong was introduced
    # that we need to use it applies the protection to a wider range of
    # function than "-fstack-protector" and will cover some corner cases
    SSP_TYPE := -fstack-protector
    GNU_VER_4_9 := 40900
    GNU_CUR_VER := $(shell $(CC) -dumpversion | sed -e 's/\./0/g')
    USE_SSP_STRONG := $(shell [ $(GNU_CUR_VER) -ge $(GNU_VER_4_9) ] && echo true )
    ifeq ($(USE_SSP_STRONG),true)
        SSP_TYPE := -fstack-protector-strong
    endif
    ARM_OPT_CC += $(SSP_TYPE)
else ifeq ($(TOOLCHAIN),CLANG)
    ARM_OPT_CC += -fstack-protector-strong
else
    ARM_OPT_CC += --protect_stack
endif

# ASM options
ARM_OPT_ASM := $(TARGET)
ifneq ($(filter $(TOOLCHAIN),GNU CLANG),)
    ARM_OPT_ASM += -DPLAT=$(ARM_PLAT)
    ARM_OPT_ASM += -DARM_ARCH=$(ARM_ARCH) -D__$(ARM_ARCH)__
    ARM_OPT_ASM += -D__$(ARM_CHIP)__
    ARM_OPT_ASM += -D__$(ARM_PLAT)__
else
    ARM_OPT_ASM += --cpreproc_opts='--c90,-DPLAT=$(ARM_PLAT),-DARM_ARCH=$(ARM_ARCH),-D__$(ARM_ARCH)__,-D__$(ARM_CHIP)__,-D__$(ARM_PLAT)__'
endif

ifeq ($(TA_PIE),PIE)
    ARM_OPT_CC += -fpie
    GNU_OPT_LINK := -Xlinker -pie
endif

# ************************************************************************************************
# Debug options

ifeq ($(MODE),Debug)
   CC_DBG_OPTS := -DDEBUG --debug

   ifeq ($(TOOLCHAIN),GNU)
        ASM_DBG_OPTS :=  -Wa,-g,--keep-locals
   else ifeq ($(TOOLCHAIN),ARM)
        ASM_DBG_OPTS :=  -g \
                         --keep
   endif

   ifeq ($(TOOLCHAIN),ARM)
      LINK_DBG_OPTS := --debug
   endif

else
   ifeq ($(TOOLCHAIN),ARM)
      LINK_DBG_OPTS := --no_comment_section
      # With --no_debug, the axf decoding into lst2 file does not know
      # about thumb or arm mode. It does not change size of tlbin.
      LINK_DBG_OPTS += --no_debug
   endif

endif

ifeq ($(MODE),Release)
    ifeq ($(BUILD_WITH_DEBUG_SYMBOLS),TRUE)
        ifeq ($(TOOLCHAIN),ARM)
            # CC debug options
            CC_DBG_OPTS := --debug
            # ASM debug options
            ASM_DBG_OPTS := --keep
            ASM_DBG_OPTS += -g
            # Link debug options
            LINK_DBG_OPTS := --debug
        endif
    endif
endif

# ************************************************************************************************
# ************************************************************************************************
# ************************************************************************************************
# Standard options
TA_NO_OF_THREADS ?= 1
TA_PARAM += -servicetype $(TA_SERVICE_TYPE) \
            -numberofthreads $(TA_NO_OF_THREADS) \
            -numberofinstances $(TA_INSTANCES) \
            -memtype $(TA_MEMTYPE) \
            -flags $(TA_FLAGS) \
            -bin $(TA_AXF) \
            -output $(TA_BIN) \
            $(GP_LEVEL) \
            $(GP_UUIDKEYFILE) \
            -interfaceversion $(TA_INTERFACE_VERSION) \
            $(DOWNGRADE_PROTECTED) \
            $(TA_HEAP_SIZE_INIT_PARAM) \
            $(TA_HEAP_SIZE_MAX_PARAM) \
            $(TA_ADD_FLAGS)

ifeq ($(TA_KEYFILE),)
TA_PARAM += --nosign
    ifneq ($(ENCRYPT_SERVICE_KEY),)
        $(error ERROR : Can only encrypt signed services.)
    endif
else
    TA_PARAM += -keyfile $(TA_KEYFILE)
endif

ifneq ($(ENCRYPT_SERVICE_KEY),)
# fill in the argument for MobiConvert to encrypt the Service signed blob
# TODO: HSM part is not covered.
SERVICE_ENCRYPT_PARAMS := -encrypt \
                          -signedbin $(TA_BIN) \
                          -output $(TA_BIN) \
                          -keyfile $(ENCRYPT_SERVICE_KEY)
endif

ifeq ($(TA_TYPE_OPTS),)
    ifeq ($(GP_ENTRYPOINTS),Y)
        TA_TYPE_OPTS := -DTRUSTEDAPP
    else
        TA_TYPE_OPTS := -DTRUSTLET
    endif
endif

TA_CC_OPTS ?=
TA_CC_OPTS += $(TA_TYPE_OPTS)
ifneq ($(filter $(TOOLCHAIN),GNU CLANG),)
TARGET += -mthumb
ifeq ($(TOOLCHAIN),GNU)
CC_OPTS := -Os
CC_OPTS += -mthumb-interwork
CC_OPTS += -fstack-usage
else
CC_OPTS := -Oz
endif
CC_OPTS += -fdata-sections
CC_OPTS += -ffunction-sections
CC_OPTS += -fno-short-enums
CC_OPTS += -nostdlib
CC_OPTS += $(TA_CC_OPTS)
CC_OPTS += $(ARM_OPT_CC)
CC_OPTS += $(CC_DBG_OPTS)
CC_OPTS += $(ARMCC_COMPILATION_FLAGS)

else
CC_OPTS :=  -D__ARMCC__ \
            --thumb \
            --apcs=interwork \
            --reduce_paths \
            --diag_style=gnu \
            --depend_format=unix_escaped \
            --no_depend_system_headers \
            --gnu \
            --bss_threshold=0 \
            --enum_is_int \
            --interface_enums_are_32_bit \
            --wchar32 \
            -O3 \
            -Ospace \
            $(TA_CC_OPTS) \
            -J$(ARM_RVCT_PATH_INC) \
            $(ARM_OPT_CC) \
            $(CC_DBG_OPTS) \
            ${ARMCC_COMPILATION_FLAGS}

# Avoid optimized memcpy in struct accesses etc, to avoid undef ref __aeabi_memmove etc when compiling with gcc
CC_OPTS_LIB_SPECIFIC := --library_interface=none
endif

# NOTE: The TA-TDriver library should be compiled without floating-point,
#       if no (float) in the interface, otherwise the compiler complains
#       when compiling the TA, if the TA does not use FP itself.
#       Here the driver developer can define its own cpu settings for the lib.
CC_OPTS_LIB := \
	$(CC_OPTS) \
	$(TARGET_LIB) \
	$(CC_OPTS_LIB_SPECIFIC)

# Now that lib is sure to be "no neon" add fpu config to generic OPTS
CC_OPTS += $(TARGET)

TA_LINK_OPTS ?=
ifneq ($(filter $(TOOLCHAIN),GNU CLANG),)
    ASM_OPTS := $(ARM_OPT_ASM) \
                ${ARMCC_COMPILATION_FLAGS} \
                $(ASM_DBG_OPTS) \
                -c
ifeq ($(TOOLCHAIN),GNU)
    ASM_OPTS += -mthumb-interwork
endif
else
    ASM_OPTS := --arm \
                --apcs=interwork \
                --reduce_paths \
                --diag_style=gnu \
                --cpreproc \
                --cpreproc_opts='-D__ARMCC__' \
                $(ARM_OPT_ASM) \
                $(ASM_DBG_OPTS)
    comma:= ,
    empty:=
    space:= $(empty) $(empty)
    tmp = $(subst $(space),$(comma),$(strip $(ARMCC_COMPILATION_FLAGS)))
    ifneq ($(tmp),)
        ASM_OPTS += --cpreproc_opts='$(tmp)'
    endif
endif

ifneq ($(filter $(TOOLCHAIN),GNU CLANG),)
ifeq ($(TOOLCHAIN),CLANG)
LINK_OPTS := $(TARGET)
endif
LINK_OPTS += -nostdlib
LINK_OPTS += -Xlinker --gc-sections
LINK_OPTS += -Xlinker --fatal-warnings
LINK_OPTS += -Xlinker --allow-multiple-definition
ifeq ($(TOOLCHAIN),GNU)
LINK_OPTS += -Xlinker --no-wchar-size-warning
LINK_OPTS += -Xlinker --no-enum-size-warning
LINK_OPTS += -Xlinker --build-id=none
endif
LINK_OPTS += -T $(LINKER_SCRIPT)
LINK_OPTS += $(GNU_OPT_LINK)
LINK_OPTS += -o $(TA_AXF)
LINK_OPTS += $(TA_LINK_OPTS)
else
LINK_OPTS := --entry _tlEntry \
            --reduce_paths \
            --diag_style=gnu \
            --datacompressor=off \
            --verbose \
            --map \
            --callgraph \
            --remove \
            --symbols \
            $(ARM_OPT_LINK) \
            --list=$(OUTPUT_PATH)/$(OUTPUT_NAME).lst \
            --libpath=$(ARM_RVCT_PATH_LIB) \
            --scatter=$(LINKER_SCRIPT) \
            -o $(TA_AXF) \
            $(LINK_DBG_OPTS) \
            $(EXTRA_LINK_OPTS) \
            --remarks \
            $(TA_LINK_OPTS)

# No section matches pattern *(heap)
LINK_OPTS += --diag_suppress=L6314W
# Pattern *(RW) only matches removed unused sections.
LINK_OPTS += --diag_suppress=L6329W
# Your license for Linker (feature armlink5) will expire in XX days
# Mark as remark: C9933W: Waiting for license...
LINK_OPTS += --diag_suppress=9931,9933

endif

ifneq ($(filter $(TOOLCHAIN),GNU CLANG),)
ARCHIVER_OPTS := -rcs
else
ARCHIVER_OPTS := --create \
             --debug_symbols \
             -v
endif

# ************************************************************************************************
# Actual sets of files to work on
SRC := $(SRC_C) $(SRC_CPP) $(SRC_ASM)
TASDK_SRC := $(TASDK_SRC_C) $(TASDK_SRC_ASM)

SRC_OBJ = $(addprefix $(OUTPUT_OBJ_PATH)/,$(join $(dir $(SRC)), $(addsuffix .o,$(notdir $(basename $(SRC))))))
TASDK_OBJ = $(addprefix $(OUTPUT_OBJ_PATH)/,$(addsuffix .o,$(notdir $(basename $(TASDK_SRC)))))
OBJ := $(SRC_OBJ) $(TASDK_OBJ)

ifneq ($(strip $(SRC_LIB_C)),)
TA_LIB_OBJ = $(addprefix $(OUTPUT_OBJ_PATH)/,$(addsuffix .ol, $(basename $(SRC_LIB_C))))
endif

INC := $(INCLUDE_DIRS:%=-I%) $(TASDK_DIR_INC:%=-I%)

LIBS := $(TLENTRY_LIB) $(TLAPI_LIB) $(GPAPI_LIB)
ifeq ($(GP_ENTRYPOINTS),Y)
LIBS += $(GPENTRY_LIB)
endif
LIBS += $(EXTRA_LIBS) ${CUSTOMER_DRIVER_LIBS} $(CUSTOMER_TA_LIBS)

ifeq ($(TOOLCHAIN),GNU)
   READ_OPT=-a $(TA_AXF) > $(TA_LST2); $(OBJDUMP) -D $(TA_AXF) >> $(TA_LST2)
   READ_OPT_LIB=-a $(TA_LIB) > $(TA_LIB).lst2; $(OBJDUMP) -D $(TA_LIB) >> $(TA_LIB).lst2
   C99=-std=c99
   CPP=-cpp
else ifeq ($(TOOLCHAIN),CLANG)
   READ_OPT=--file-headers --program-headers --sections --symbols --relocations --notes --version-info -elf-section-groups $(TA_AXF) > $(TA_LST2); $(OBJDUMP) -D -triple=$(TRIPLE) $(TA_AXF) >> $(TA_LST2)
   READ_OPT_LIB=-a $(TA_LIB) > $(TA_LIB).lst2; $(OBJDUMP) -D $(TA_LIB) >> $(TA_LIB).lst2
   C99=-std=c99
   CPP=-cpp
else
   READ_OPT=--text -c -d -e -s -t -z --datasymbols $(TA_AXF) --output $(TA_LST2)
   READ_OPT_LIB=--text -c -d -e -s -t -z --datasymbols $(TA_LIB) --output $(TA_LIB).lst2
   C99=--c99
   CPP=--cpp
endif

###################################################################
# Samsung change : Set signing option of TA and secure drivers
###################################################################
ifneq ($(TRUSTLET_SIGN_CONF),)
	SIGN_CLIENT_CONF_STR=-conf_str $(TRUSTLET_SIGN_CONF)
else 
ifneq ($(TRUSTLET_DRV_SIGN_CONF),)
	SIGN_CLIENT_CONF_STR=$(TRUSTLET_DRV_SIGN_CONF)
else
	$(info [ERROR] No signing option is given !!! Please set TRUSTLET_SIGN_CONF for TAs, TRUSTLET_DRV_SIGN_CONF for secure drivers.)
endif
endif	

# ************************************************************************************************
# Rules

ifeq ($(TA_LIB_OBJ),)
   OBJDIRS := $(sort $(dir $(OBJ)))
   OBJDIRS += $(sort $(dir $(LIBS)))
else
   OBJDIRS := $(sort $(dir $(TA_LIB_OBJ)))
   OBJDIRS += $(sort $(dir $(OBJ)))
   OBJDIRS += $(OUTPUT_PATH_INDEPENDENT)
endif

ifeq ($(GP_ENTRYPOINTS),Y)
all : $(UUID_H) $(GP_BIN) $(TA_LIB)
else
ifdef TA_LIB_OBJ
all : $(TA_BIN) $(TA_LIB)
else
all : $(TA_BIN)
endif
endif

$(OBJDIRS):
	@mkdir -p $@

$(TA_AXF) : $(OBJDIRS) $(OBJ) $(LIBS)
	$(info ******************************************)
	$(info ** LINKER ********************************)
	$(info ******************************************)
	$(LINKER) $(LINK_OPTS) $(OBJ) $(LIBS) $(STD_LIBS)
ifeq ($(TOOLCHAIN),GNU)
ifneq ("$(wildcard $(COMP_PATH_Scripts)/perl/avstack.pl)","")
	$(COMP_PATH_Scripts)/perl/avstack.pl $(OBJ) > $(TA_AXF).txt
endif
endif

$(TA_BIN) : $(TA_AXF)
	$(info ******************************************)
	$(info ** READELF & MobiConvert *****************)
	$(info ******************************************)
	$(READELF) $(READ_OPT)
ifeq ($(SIGNING_TYPE),samsung_mobile)
#	For Samsung Device (New Signinig)
	java -jar $(TASDK_DIR_SRC)/Bin/MobiConvert/signclient.jar -model $(MODEL) -runtype $(RUNTYPE) -input $(TA_AXF) -output $(TA_BIN) $(SIGN_CLIENT_CONF_STR) | size $(TA_AXF) > $(TOPDIR)/trustedapps_temp
else
ifneq ($(GP_TA_PROP_PARAM),)
	java -jar $(TASDK_DIR_SRC)/Bin/MobiConvert/MobiConvert.jar $(GP_TA_PROP_PARAM)
endif
	java -jar $(TASDK_DIR_SRC)/Bin/MobiConvert/MobiConvert.jar $(TA_PARAM) >$(TA_LOG_FILE_NAME)
ifeq ($(TA_KEYFILE),)
	mv $(TA_BIN).raw $(TA_BIN)
endif
endif
ifdef ADDITIONAL_BIN_EXT
	cp $(TA_BIN) $(OUTPUT_PATH)/$(TA_UUID).$(ADDITIONAL_BIN_EXT)
endif

# encrypt the service
ifneq ($(ENCRYPT_SERVICE_KEY),)
	$(info ******************************************)
	$(info ** Encrypting Service using MobiConvert **)
	$(info ******************************************)
	java -jar $(TASDK_DIR_SRC)/Bin/MobiConvert/MobiConvert.jar $(SERVICE_ENCRYPT_PARAMS) >$(ENCRYPTED_TA_LOG_FILE_NAME)
endif

ifeq ($(TA_SERVICE_TYPE),2)
ifneq ($(GP_BIN),$(TA_BIN))
$(GP_BIN) : $(TA_BIN)
	$(info ******************************************)
	$(info ** Copy tabin with GP UUID name **********)
	$(info ******************************************)
	cp $(TA_BIN) $(GP_BIN)
	-rm -f $(TA_BIN)
endif
endif

$(UUID_H) :
	$(info ******************************************)
	$(info ** UUID header file creation    **********)
	$(info ******************************************)
	@mkdir -p "$(dir $(UUID_H))"
	$(TASDK_DIR_SRC)/uuid2header.sh $(OUTPUT_NAME) $(GP_UUID) $(UUID_H)

$(TA_LIB) : $(TA_LIB_OBJ)
	$(ARCH) $(ARCHIVER_OPTS) $(TA_LIB) $(TA_LIB_OBJ)
	$(READELF) $(READ_OPT_LIB)

.PHONY: clean

clean :
	-rm -rf $(OUTPUT_PATH)/*

clean_all :
	-rm -rf $(OUTPUT_ROOT)/*/*

$(OUTPUT_OBJ_PATH)/%.o : %.c $(OBJDIRS)
	$(CC) $(C99) $(CC_OPTS) $(CC_OPTS2) $(INC) -c -o $@ $<

$(OUTPUT_OBJ_PATH)/%.o : %.cpp $(OBJDIRS)
	$(CC) $(CPP) $(CC_OPTS) $(INC) -c -o $@ $<

$(OUTPUT_OBJ_PATH)/%.ol : %.c
	mkdir -p $(dir $@)
	$(CC) $(C99) $(CC_OPTS_LIB) $(INC) -c -o $@ $<

$(OUTPUT_OBJ_PATH)/%.o : %.s $(OBJDIRS)
	$(ASM) $(ASM_OPTS) $(INC) -o $@ $<

$(OUTPUT_OBJ_PATH)/%.o : %.S $(OBJDIRS)
	$(ASM) $(ASM_OPTS) $(INC) -o $@ $<
# ************************************************************************************************
