# Build t-base.

# Common parameters:
# - LOCAL_SDK_PATH
# - LOCAL_NAME
# Optional:
# - LOCAL_BUILD_TOOL
# - LOCAL_ARMCC_PATH
# - LOCAL_ARMCC_LICENSE
# - LOCAL_CROSS_GCC_PATH
# - LOCAL_CROSS_GCC_PATH_LGCC
# - LOCAL_INCLUDE_DIRS
# - LOCAL_SRC_LIB_C
# - LOCAL_SRC_CPP
# - LOCAL_SRC_C
# - LOCAL_SRC_S
# - LOCAL_CFLAGS
# - LOCAL_CPPFLAGS
# - LOCAL_CUSTOM_LIBS
# - LOCAL_STATIC_LIBRARIES
# - LOCAL_API_LEVEL (3 is by default)
# - LOCAL_SHRINK_PROTOCOL_BUFFER

_sdk_dir := $(realpath $(dir $(lastword $(MAKEFILE_LIST))))

include $(_sdk_dir)/tbase-utils.mk
include $(_sdk_dir)/path-utilities.mk

##########################
# Strip input parameters #
##########################

LOCAL_SDK_PATH := $(strip $(LOCAL_SDK_PATH))
LOCAL_BUILD_TOOL := $(strip $(LOCAL_BUILD_TOOL))
LOCAL_ARMCC_PATH := $(strip $(LOCAL_ARMCC_PATH))
LOCAL_ARMCC_LICENSE := $(strip $(LOCAL_ARMCC_LICENSE))
LOCAL_LINK_GP_TEE := $(strip $(LOCAL_LINK_GP_TEE))
LOCAL_API_LEVEL := $(strip $(LOCAL_API_LEVEL))
LOCAL_GROUP_ID := $(strip $(LOCAL_GROUP_ID))
LOCAL_FIPS_CRYPTO := $(strip $(LOCAL_FIPS_CRYPTO))
LOCAL_IMPRINT_TOOL := $(strip $(LOCAL_IMPRINT_TOOL))
LOCAL_OUT := $(strip $(LOCAL_OUT))

####################################
# Check necessary input parameters #
####################################

ifeq ($(LOCAL_BUILD_TOOL),)
  LOCAL_BUILD_TOOL := arm
endif

ifeq ($(LOCAL_FIPS_CRYPTO),)
  LOCAL_FIPS_CRYPTO := n
endif

ifeq ($(LOCAL_BUILD_TOOL),arm)
  ifeq ($(LOCAL_ARMCC_PATH),)
    $(error LOCAL_ARMCC_PATH is not specified)
  endif

  ifeq ($(LOCAL_ARMCC_LICENSE),)
    $(error LOCAL_ARMCC_LICENSE is not specified)
  endif
else
  ifeq ($(LOCAL_CROSS_GCC_PATH),)
    LOCAL_CROSS_GCC_PATH := /usr/lib/arm-none-eabi
  endif
  ifeq ($(LOCAL_CROSS_GCC_PATH_LGCC),)
    LOCAL_CROSS_GCC_PATH_LGCC := $(lastword $(wildcard /usr/lib/gcc/arm-none-eabi/*))
  endif
endif

ifeq ($(LOCAL_LINK_GP_TEE),y)
  ifeq ($(LOCAL_GROUP_ID),)
    LOCAL_GROUP_ID := dev_ta
  endif

  ifeq ($(LOCAL_UUID),)
    $(error LOCAL_UUID is not specified)
  endif
else
  LOCAL_LINK_GP_TEE := n
endif

ifeq ($(LOCAL_API_LEVEL),)
  LOCAL_API_LEVEL := 3
  ifeq ($(call get-tbase-version,$(LOCAL_SDK_PATH)),5xx)
    LOCAL_API_LEVEL := 11
  endif
endif

ifeq ($(LOCAL_IMPRINT_TOOL),)
  ifeq ($(LOCAL_FIPS_CRYPTO),y)
    # If imprint tool is not set and fips crypto selected, use default imprint
    LOCAL_IMPRINT_TOOL := $(_sdk_dir)/../tools/imprint
  endif
endif

ifeq ($(LOCAL_OUT),)
  LOCAL_OUT := $(abspath ./out)
endif

ifeq ($(LOCAL_SHRINK_PROTOCOL_BUFFER),y)
  LOCAL_CFLAGS += -DSHRINK_PROTOCOL_BUFFER
endif

####################################
# Check of user input parameters   #
####################################

include $(_sdk_dir)/rules-utils.mk
$(call tbase-build-rules)

#####################################################
# Output directory uniquely defines the main target #
#####################################################

_local_output_base := $(call get-absolute-path,$(LOCAL_OUT)/$(LOCAL_TARGET_NAME:=/)tbase)
_local_output_dir := $(_local_output_base)/$(LOCAL_NAME)

##################
# Set up sources #
##################

LOCAL_SRC_LIB_C := $(call get-absolute-path,$(LOCAL_SRC_LIB_C))
LOCAL_SRC_CPP := $(call get-absolute-path,$(LOCAL_SRC_CPP))
LOCAL_SRC_C := $(call get-absolute-path,$(LOCAL_SRC_C))
LOCAL_SRC_S := $(call get-absolute-path,$(LOCAL_SRC_S))

#########################
# Handle LOCAL_EXPORT_* #
#########################

include $(_sdk_dir)/local-export.mk

$(call save-all-local-export,tbase,$(LOCAL_TARGET_NAME:=),$(LOCAL_NAME))

$(foreach _lib,$(LOCAL_STATIC_LIBRARIES), \
  $(call restore-all-local-export,tbase,$(LOCAL_TARGET_NAME:=),$(_lib)))

LOCAL_INCLUDE_DIRS := $(call get-absolute-path,$(LOCAL_INCLUDE_DIRS)) \
                      $(call get-tbase-include-paths,$(LOCAL_SDK_PATH))

#################
# Is it driver? #
#################

_entry := _tlEntry
_scatter := $(strip $(call get-tbase-tlsdk-path,$(LOCAL_SDK_PATH))/trusted_application.sct)
_linker_script := $(strip $(call get-tbase-tlsdk-path,$(LOCAL_SDK_PATH))/trusted_application.ld)

ifneq ($(call get-tbase-version,$(LOCAL_SDK_PATH)),5xx)
  _entry_lib := $(call get-tbase-tlsdk-path,$(LOCAL_SDK_PATH))/Bin/TlEntry/TlEntry.lib
  _tl_api_lib := $(call get-tbase-tlsdk-path,$(LOCAL_SDK_PATH))/Bin/TlApi/TlApi.lib
  _api_lib := $(_tl_api_lib)
else
  _entry_lib := $(call get-tbase-tlsdk-path,$(LOCAL_SDK_PATH))/Bin/ARM_V7A_STD/TlEntry/PIE/TlEntry.lib
  _tl_api_lib := $(call get-tbase-tlsdk-path,$(LOCAL_SDK_PATH))/Bin/ARM_V7A_STD/TlApi/PIE/TlApi.lib
  _api_lib := $(_tl_api_lib) \
              $(call get-tbase-tlsdk-path,$(LOCAL_SDK_PATH))/Bin/ARM_V7A_STD/GpApi/PIE/GpApi.lib
endif
_ta_flags :=
_drv :=
-driver :=

ifneq ($(findstring _drv,$(LOCAL_GROUP_ID)),)
  _driver := _driver
  _drv := _drv
  -driver := -driver
  _entry := _drEntry
  _scatter := $(strip $(call get-tbase-drsdk-path,$(LOCAL_SDK_PATH))/dr.sct)

  ifneq ($(call get-tbase-version,$(LOCAL_SDK_PATH)),5xx)
    _linker_script := $(strip $(call get-tbase-drsdk-path,$(LOCAL_SDK_PATH))/driver.ld)
    _entry_lib := $(call get-tbase-drsdk-path,$(LOCAL_SDK_PATH))/Bin/DrEntry/DrEntry.lib
    _dr_api_lib := $(call get-tbase-drsdk-path,$(LOCAL_SDK_PATH))/Bin/DrApi/DrApi.lib
    _api_lib :=

    # Needed for tlApiDeriveKey() in driver.
    # Due to symbol duplication between DrApi.lib and TlApi.lib
    # we have to make duplicated symbols from TlApi.lib weak.
    LOCAL_CUSTOM_LIBS += $(_local_output_dir)/TlApi_patched.lib
  else
    _entry_lib += $(call get-tbase-drsdk-path,$(LOCAL_SDK_PATH))/Bin/ARM_V7A_STD/DrEntry/PIE/DrEntry.lib
    _dr_api_lib := $(call get-tbase-drsdk-path,$(LOCAL_SDK_PATH))/Bin/ARM_V7A_STD/DrApi/PIE/DrApi.lib
  endif

  _api_lib += $(_dr_api_lib)
  _ta_flags := -DDRIVER
endif

###################
# Set up compiler #
###################


# Define special C flags (set into LOCAL_CFLAGS)
_arm_arch := ARMv7
_arm_chip := ARMV7_A
_arm_shape := STD
_arm_platform := $(_arm_chip)_$(_arm_shape)

_arm_defines := -DPLAT=$(_arm_platform)
_arm_defines += -DARM_ARCH=$(_arm_arch) -D__$(_arm_arch)__
_arm_defines += -D__$(_arm_chip)__
_arm_defines += -D__$(_arm_platform)__
_arm_defines += -D$(_arm_chip)_SHAPE=$(_arm_shape)
_arm_defines += -DTBASE_API_LEVEL=$(LOCAL_API_LEVEL)
_arm_defines += -D__THUMB__

# Erase stack protection flags by default (not preserve between modules).
_stack_protect_flags :=

# FIPS symbols should be kept because SCRYPTO imprint tool require these symbols.
# Format is the same for arm as well as fo llvm.
_keep_fips_symbols := --keep-symbol=FIPS_bssl_text_start \
                      --keep-symbol=FIPS_bssl_text_end \
                      --keep-symbol=FIPS_bssl_rodata_start \
                      --keep-symbol=FIPS_bssl_rodata_end \
                      --keep-symbol=FIPS_embedded_hmac

ifeq ($(LOCAL_BUILD_TOOL),arm)
    export LM_LICENSE_FILE := $(LOCAL_ARMCC_LICENSE)
    _arm_path_bin := $(LOCAL_ARMCC_PATH)/bin
    _arm_path_lib := $(LOCAL_ARMCC_PATH)/lib
    _arm_path_inc := $(LOCAL_ARMCC_PATH)/include
    _cc := $(_arm_path_bin)/armcc
    _cxx := $(_arm_path_bin)/armcc --cpp
    _ld := $(_arm_path_bin)/armlink
    _ar := $(_arm_path_bin)/armar
    _objcpy := $(strip $(call -search-arm-build-tool,$(LOCAL_ARMCC_PATH),objcopy))

    _strip  := $(strip $(call -search-arm-build-tool,$(LOCAL_ARMCC_PATH),strip)) $(_keep_fips_symbols)

    _compiler_flags := --cpu=7-A
    _compiler_flags += --fpu=SoftVFP

    # Warning/Error 66 should be suppressed because it breaks compiling some modules
    # which use unsigned values in enums, i.e. internal_tee_api
    _compiler_flags += --diag_suppress 66

    # Warnings/Errors 9931/9932/9933 should be suppressed
    # because it dependes on availability of license DS-5
    _compiler_flags += --diag_remark=9931 \
                   --diag_remark=9932 \
                   --diag_remark=9933

    _compiler_flags += \
                -D__ARMCC__ \
                -D_AEABI_PORTABILITY_LEVEL=0 \
                --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 \
                -O2 \
                -Ospace \
                -J$(_arm_path_inc) \

    _std_c := --c99

    _start_group :=
    _end_group :=

    ifeq ($(LOCAL_LINK_GP_TEE),y)
      _stack_protect_flags := --protect_stack --protect_stack_all
    endif

    LOCAL_LDFLAGS += \
                --entry $(_entry) \
                --reduce_paths \
                --diag_style=gnu \
                --datacompressor=off \
                --verbose \
                --map \
                --callgraph \
                --remove \
                --symbols \
                --list=$(strip $(_local_output_dir)/$(LOCAL_NAME).lst) \
                --libpath=$(strip $(_arm_path_lib)) \
                --scatter=$(strip $(_scatter)) \

else
    _cc := clang-3.9
    _cxx := clang-3.9
    _ld := arm-none-eabi-ld
    _ar := arm-none-eabi-ar
    _objcpy := arm-none-eabi-objcopy

    _strip := arm-none-eabi-strip $(_keep_fips_symbols)

    _compiler_flags := \
                -g -ggdb \
                -mthumb \
                -fshort-wchar \
                -fno-short-enums \
                -Os \
                -Wno-unknown-attributes \
                -Wno-extern-initializer \
                -nostdinc \
                -I $(strip $(LOCAL_CROSS_GCC_PATH))/include \
                -I $(strip $(LOCAL_CROSS_GCC_PATH_LGCC))/include \
                -I $(strip $(LOCAL_CROSS_GCC_PATH_LGCC))/include-fixed \
                --target=armv7-none-gnueabi \
                -mfpu=vfp \
                -mfloat-abi=soft \
                -ffunction-sections \
                -fdata-sections

    _std_c := -std=c11

    _start_group := --start-group
    _end_group := --end-group

    ifeq ($(LOCAL_LINK_GP_TEE),y)
      _stack_protect_flags := -fstack-protector-strong
    endif

    # Code generation options for clang to match DS-5 version 5
    _clang_code_gen_flags := \
                -Xclang -target-feature -Xclang -trustzone \
                -Xclang -target-feature -Xclang -virtualization \
                -Xclang -target-feature -Xclang -vfp2 \
                -Xclang -menable-no-infs \
                -Xclang -menable-no-nans \
                -Xclang -menable-unsafe-fp-math \
                -Xclang -target-feature -Xclang -reserve-r9

    _compiler_flags += $(_clang_code_gen_flags)

    LOCAL_LDFLAGS += \
            -nostdlib \
            -lc -lm -lgcc \
            --gc-sections \
            -T $(strip $(_linker_script)) \
            -L $(strip $(LOCAL_CROSS_GCC_PATH))/lib \
            -L $(strip $(LOCAL_CROSS_GCC_PATH_LGCC)) \
            -Map=$(strip $(_local_output_dir)/$(LOCAL_NAME).map) \
            --fatal-warnings \
            --no-wchar-size-warning \
            --no-enum-size-warning \


endif

ifeq ($(call get-tbase-version,$(LOCAL_SDK_PATH)),5xx)
  LOCAL_CFLAGS += -DKINIBI_VERSION=5
  LOCAL_CPPFLAGS += -DKINIBI_VERSION=5
else
  LOCAL_CFLAGS += -DKINIBI_VERSION=4
  LOCAL_CPPFLAGS += -DKINIBI_VERSION=4
endif

_arm_flags := \
            $(_compiler_flags) \
            $(TA_CC_OPTS) \
            $(_arm_defines) \
            $(addprefix -I,$(INCLUDE_DIRS))

# Add stack protector before the possible module's overwrite - this will make
# possible to disable stack protector explicitly if the module doesn't implement
# this.
_tmp_cflags := $(_stack_protect_flags) $(_arm_flags) $(_ta_flags) $(_std_c) $(LOCAL_CFLAGS)
_tmp_cppflags := $(_stack_protect_flags) $(_arm_flags) $(_ta_flags) $(LOCAL_CPPFLAGS)

LOCAL_CFLAGS := $(_tmp_cflags)
LOCAL_CPPFLAGS := $(_tmp_cppflags)


########################################################
# Define targets for patching TlApi library for driver #
########################################################

ifneq ($(findstring _drv,$(LOCAL_GROUP_ID)),)
$(_local_output_dir)/TlApi_patched.lib: _objcpy := $(_objcpy)
$(_local_output_dir)/TlApi_patched.lib: $(_tl_api_lib)
	mkdir -p $(dir $(@))
	$(_objcpy) -w -W TEE_* $(<) $(@)
endif
