include config/config.mk

ifeq ($(wildcard multibuild/sdk.mk),)
  $(info ******************************************************************)
  $(info * Multibuild SDK is not found in the ./multibuild folder.        *)
  $(info * Please, mount or copy appropriate version of Multibuild SDK    *)
  $(info * into ./multibuild folder.                                      *)
  $(info ******************************************************************)
  $(error multibuild/sdk.mk is absent)
endif

ifeq ($(wildcard tests/Makefile),)
  $(warning tests/Makefile is absent. Did you run fix_path script in tests directory?)
  TESTS_ARE_ABSENT := TRUE
endif

include multibuild/sdk.mk

### Add target platforms #######################################################
include config/targets.mk

###  Default configuration to install ##########################################
include config/detect_deploy_target.mk

### CI environment #############################################################
CI_WHO ?= $(USER)

### Build release ##############################################################
ifeq ($(Release),yes)
  $(info ------ Release is building...)
  export PA_GLOBAL_CFLAGS := -DRELEASE_PA -DNDK_DEBUG=0 -DVERSION_SUFFIX=\",version_$(shell cat VERSION),release,$(CI_WHO)\"
else
  export PA_GLOBAL_CFLAGS := -g -DDEBUG_PA -DNDK_DEBUG=1 -DVERSION_SUFFIX=\",version_$(shell cat VERSION),debug,$(CI_WHO)\"
endif

### Disable Five authentication ################################################
ifeq ($(Skip_auth),yes)
  $(info ----- Disabled five authentication...)
  export PA_GLOBAL_CFLAGS += -DSKIP_FIVE_AUTH
endif

### Common flags ###############################################################
# Few points to use -O0 everywhere:
# 1. We have performance degradation with other optimization flags for LLVM toolchain
# 2. It is one of the mitigations for undefined behaviour
export PA_GLOBAL_CFLAGS += -O0

### Disable signing ############################################################
JUST_BUILD := $(filter $(MAKECMDGOALS),build)

### Build GTest library ########################################################
LOCAL_NAME := gtest_main
LOCAL_INCLUDE_DIRS := multibuild/source/gtest/include
LOCAL_SRC_CPP := multibuild/source/gtest/source/gtest-all.cc \
                 multibuild/source/gtest/source/gtest_main.cc

# Disable Test that marked as Big (long running unit-tests) by default
# To enable these tests set GTEST_FILTER to *
ifndef GTEST_FILTER
export GTEST_FILTER=-*BigTest*
endif

LOCAL_EXPORT_INCLUDE_DIRS := multibuild/source/gtest/include
LOCAL_EXPORT_CFLAGS := --coverage
LOCAL_EXPORT_CPPFLAGS := --coverage
include $(BUILD_HOST_LIBRARY)

### Build SCL library ##########################################################
include scl/scl.mk

### Build ASN1C library ########################################################
include asn1/asn1lib.mk

### Build tools ################################################################
include tools/tools.mk

LCOV := lcov --rc lcov_branch_coverage=1 -q
GENHTML := genhtml --rc lcov_branch_coverage=1

### Build Android ##############################################################
LOCAL_NDK_PATH := $(CONFIG_ANDROID_NDK_PATH)
LOCAL_PROJECTS := pa_daemon pa_nwd_lib
LOCAL_PLATFORM_VERSION := android-28
include $(BUILD_ANDROID)

### Add targets for significant Android output
./out/android/pa_nwd_lib/local/arm64-v8a/libpa.so: pa_nwd_lib

### Build PA driver ############################################################
include pa_tz_drv/pa_tz_drv.mk

### Build pa_tz_api library ####################################################
include pa_tz_lib/pa_tz_lib.mk

### Build pa_nwd_api unit tests ################################################
include pa_nwd_lib/tests/pa_nwd_lib_tests.mk

### Custom targets #############################################################
# 1 arg is platform; 2 arg is path to copy pa_tz_api; 3 is extension (a or lib)
define deploy_swd
	@mkdir -p $(2); \
	cp -vf pa_tz_lib/pa_tz_lib_ship.mk $(2)/pa_tz_lib.mk; \
	mkdir -p ./out/temp_$(1); \
	cp ./out/$(1)/asn1proto/asn1proto.$(3) ./out/temp_$(1); \
	cp ./out/$(1)/pa_tz_api/pa_tz_api.$(3) ./out/temp_$(1); \
	cp ./out/$(1)/scl/scl.$(3) ./out/temp_$(1); \
	cd ./out/temp_$(1); \
	ar -x asn1proto.$(3);\
	ar -x scl.$(3);\
	ar -x pa_tz_api.$(3);\
	ar -rc pa_tz_api.a *.o;\
	cd - ; \
	cp -rvf ./out/temp_$(1)/pa_tz_api.a $(2); \
	rm -rf ./out/temp_$(1)
endef

### Targest to deploy SWD libraries ############################################
# 1 arg is target
# 2 arg is platform; 3 arg is path to copy pa_tz_api; 4 is extension (a or lib)
define deploy_swd_libs
_out := $(abspath ./out)
_path := $(abspath $(3))
.PHONY: deploy $(1)
$(1): $$(_path)/pa_tz_api.a
deploy: $$(_path)/pa_tz_api.a
$$(_path)/pa_tz_api.a: $$(_out)/$(2)/asn1proto/asn1proto.$(4)
$$(_path)/pa_tz_api.a: $$(_out)/$(2)/pa_tz_api/pa_tz_api.$(4)
$$(_path)/pa_tz_api.a: $$(_out)/$(2)/scl/scl.$(4)
$$(_path)/pa_tz_api.a:
	@echo -e "\tDeploy $(2)"
	$(call deploy_swd,$(2),$(3),$(4))

_out :=
_path :=
endef

.PHONY: build
build: run_utests deploy

DEPLOY_DIR = $(ROOT_DIR)/deploy
ANDROID_DEPLOY_PATH = $(DEPLOY_DIR)/android/pa_nwd_lib
TBASE_DEPLOY_PATH = $(DEPLOY_DIR)/tbase/pa_tz_api
BLOWFISH_DEPLOY_PATH = $(DEPLOY_DIR)/blowfish/pa_tz_api
QSEE_DEPLOY_PATH = $(DEPLOY_DIR)/qsee/pa_tz_api
INCLUDE_DEPLOY_PATH = $(DEPLOY_DIR)/include

.PHONY: deploy
deploy: $(ANDROID_DEPLOY_PATH)/arm64-v8a/libpa.so
$(ANDROID_DEPLOY_PATH)/arm64-v8a/libpa.so: ./out/android/pa_nwd_lib/local/arm64-v8a/libpa.so
	@mkdir -p $(ANDROID_DEPLOY_PATH)/arm64-v8a $(ANDROID_DEPLOY_PATH)/armeabi-v7a
	@echo -e "\tDeploy PA NWD LIB"
	@cp -vr out/android/pa_nwd_lib/arm64-v8a/libpa.so \
	$(ANDROID_DEPLOY_PATH)/arm64-v8a/libpa.so
	@cp -vr out/android/pa_nwd_lib/armeabi-v7a/libpa.so \
	$(ANDROID_DEPLOY_PATH)/armeabi-v7a/libpa.so
	@cp -vr out/android/pa_nwd_lib/local/arm64-v8a/libpa_provision.a \
	$(ANDROID_DEPLOY_PATH)/arm64-v8a/libpa_provision.a
	@cp -vr out/android/pa_nwd_lib/local/armeabi-v7a/libpa_provision.a \
	$(ANDROID_DEPLOY_PATH)/armeabi-v7a/libpa_provision.a
	@cp -vf pa_nwd_lib/Android_ship.mk $(ANDROID_DEPLOY_PATH)/Android.mk
	@echo -e "\tDeploy includes"
	@mkdir -p $(INCLUDE_DEPLOY_PATH)
	@cp -vf thirdparty/libfive/five_api.h $(INCLUDE_DEPLOY_PATH)
	@cp -vfr pa_nwd_lib/include/* $(INCLUDE_DEPLOY_PATH)
	@cp -vfr pa_tz_lib/include/* $(INCLUDE_DEPLOY_PATH)

# 1 - target
get-qsee-prefix = \
  $(call get-target-parameter,$(1),qsee,LOCAL_CHIP)_$(call get-target-parameter,$(1),qsee,LOCAL_QSEE_PROC)

# The loop to prepare deploy for all the platforms.
deploy-for-each-target = \
  $(if $(_global_target_names), \
    , \
    $(error Any target configuration is defined. Please, add at least one of by include $$(ADD_TARGET).)) \
  \
  $(foreach _target,$(_global_target_names), \
    $(foreach _platform,$(_global_target_$(_target)_platforms), \
      $(if $(filter qsee,$(_platform)), \
       $(eval $(call deploy_swd_libs,$(_target),$(_target)/$(_platform)/$(call get-qsee-prefix,$(_target)),$(DEPLOY_DIR)/$(_target)/$(_platform),lib)), \
       $(eval $(call deploy_swd_libs,$(_target),$(_target)/$(_platform),$(DEPLOY_DIR)/$(_target)/$(_platform),a)))))

$(call deploy-for-each-target)

DEVICE_APP_ABI := `adb shell getprop ro.product.cpu.abi`
DEVICE_APP_ABI_32 := armeabi-v7a

# Android P
# libpa.so locates in /vendor and in /system
# pa_daemon locates in /vendor
.PHONY: _install_nwd_components
_install_nwd_components: pa_signer
	@$(ROOT_DIR)/tools/five_push.sh out/$(DEPLOY_TARGET)/vendor.samsung.hardware.security.proca@2.0-service/$(DEVICE_APP_ABI)/vendor.samsung.hardware.security.proca@2.0-service \
		-d /vendor/bin
	@$(ROOT_DIR)/tools/five_push.sh out/android/pa_nwd_lib/$(DEVICE_APP_ABI_32)/libpa.so \
		-d /system/lib --five-only
	@if [ ${DEVICE_APP_ABI} = "arm64-v8a" ]; then $(ROOT_DIR)/tools/five_push.sh out/android/pa_nwd_lib/$(DEVICE_APP_ABI)/libpa.so \
		-d /system/lib64 --five-only ; fi
	@$(ROOT_DIR)/tools/five_push.sh out/android/pa_nwd_lib/$(DEVICE_APP_ABI_32)/libpa.so \
		-d /vendor/lib --five-only
	@if [ ${DEVICE_APP_ABI} = "arm64-v8a" ]; then $(ROOT_DIR)/tools/five_push.sh out/android/pa_nwd_lib/$(DEVICE_APP_ABI)/libpa.so \
		-d /vendor/lib64 --five-only ; fi

.PHONY: _install_tbase_components
_install_tbase_components:
	@adb push out/$(DEPLOY_TARGET)/proca/$(CONFIG_TBASE_PA_DRIVER_UUID).tlbin /vendor/app/mcRegistry

.PHONY: _install_qsee_components
_install_qsee_components:
	@firmware_dir=$$(adb shell ls -d /vendor/firmware_mnt); if [ ! "$${firmware_dir}" ]; then firmware_dir=/firmware; fi; \
	adb shell mount -o rw,remount $${firmware_dir}; \
	ls out/$(DEPLOY_TARGET)/*_A53_64 && QSEE_BIT=_A53_64 || QSEE_BIT=_scorpion; \
	adb shell mkdir -p /data/local/tmp/image_tmp; \
	for i in out/$(DEPLOY_TARGET)/*$${QSEE_BIT}/proca/signed/*; do adb push $${i} /data/local/tmp/image_tmp; done; \
	adb shell cp -fv /data/local/tmp/image_tmp/* $${firmware_dir}/image/; \
	adb shell rm -rf /data/local/tmp/image_tmp

.PHONY: _install_blowfish_components
_install_blowfish_components:
	@adb push out/$(DEPLOY_TARGET)/proca/$(strip $(call get-blowfish-local-sign-output-name,$(CONFIG_TEEGRIS_PA_DRIVER_UUID))) /vendor/tee/

.PHONY: _install_teegris_components
_install_teegris_components: _install_blowfish_components

.PHONY: _install_setup
_install_setup:
	@echo "Install Process Authenticator to $(DEPLOY_TARGET)"
	@adb remount

.PHONY: install
install: | _install_setup _install_nwd_components _install_$(DEPLOY_PLATFORM)_components
	@echo "Restart PA daemon ..."
	@adb shell "pkill proca"

.PHONY: doxygen
doxygen:
	doxygen documents/doxyfile

.PHONY: clean
clean: clean_tests

.PHONY: clean_tests
clean_tests:
ifeq ($(TESTS_ARE_ABSENT),)
	@$(MAKE) -C tests/ clean
	@$(MAKE) -C tests/functional clean
	@$(MAKE) -C tests/stress clean
else
	@true
endif

.PHONY: force_clean
force_clean: clean
ifeq ($(TESTS_ARE_ABSENT),)
	@$(MAKE) -C tests/ force_clean
	@$(MAKE) -C tests/functional force_clean
	@$(MAKE) -C tests/stress force_clean
	@$(MAKE) -C thirdparty force_clean
endif
	@rm -rf out/
	@rm -rf ship/
	@rm -rf $(DEPLOY_DIR)
	@rm -rf multibuild/source/gp-api/out
	@rm -rf tools/config_generate/out

.PHONY: tests
tests: deploy
	@$(MAKE) -C tests/ $(JUST_BUILD)

# TODO(i.vorobiov): Remove after edit TeamCity scripts
.PHONY: ftests tests
ftests stests: tests

.PHONY: run_utests

.PHONY: coverage
coverage: run_utests
	@echo -e "\n\tCollecting coverage report..."
	$(LCOV) --directory ./out/host/ --capture -o ./out/host/coverage.info
	$(LCOV) --remove ./out/host/coverage.info "usr/include/*" -o ./out/host/coverage.info
	$(LCOV) --remove ./out/host/coverage.info "include/gtest/*" -o ./out/host/coverage.info
	$(LCOV) --remove ./out/host/coverage.info "source/gtest*" -o ./out/host/coverage.info
	$(LCOV) --remove ./out/host/coverage.info "tests/*" -o ./out/host/coverage.info
	$(LCOV) --remove ./out/host/coverage.info "multibuild/*" -o ./out/host/coverage.info
	$(LCOV) --summary ./out/host/coverage.info
	$(GENHTML) --branch-coverage --output-directory ./out/host/html ./out/host/coverage.info
	@echo "Coverage report is stored in [./out/host/html/]"

.PHONY: svace
svace: asn1proto scl pa_daemon pa_nwd_lib pa_signer proca pa_tz_api deploy

thirdparty/asn1c/asn1c/asn1c:
	@$(MAKE) -C thirdparty

PROTEX_SOURCES := \
    $(shell find asn1 -name *.[ch] -type f) \
    $(shell find pa_daemon -name *.[ch] -type f) \
    $(shell find pa_nwd_lib -name *.[ch] -type f) \
    $(shell find pa_tz_drv -name *.[ch] -type f) \
    $(shell find pa_tz_lib -name *.[ch] -type f) \
    $(shell find multibuild/source/gp-api -name *.[ch] -type f) \
    $(shell find scl/arch scl/include scl/source -name *.[ch] -type f)

.PHONY: protex
protex:
	@echo "Prepare archive for Protex analyzing"
	@rm -rf protex.zip
	@zip protex.zip $(PROTEX_SOURCES)

.PHONY: bundle
bundle: pa_signer
	@mkdir -p out/bundle/config/five
	@cp -r $(ROOT_DIR)/config/five/* out/bundle/config/five
	@cp -r $(ROOT_DIR)/config/pa out/bundle/config
	@cp out/host/pa_signer/pa_signer out/bundle
	@cp $(ROOT_DIR)/tools/five_evmctl out/bundle
	@mkdir -p out/bundle/xattr/
	@cp -r $(ROOT_DIR)/tools/xattr/arm* out/bundle/xattr
	@cp $(ROOT_DIR)/tools/five_push.sh out/bundle/sign_and_push.sh.tmp
	@sed -e 's/..\/out\/host\/pa_signer\///;s/..\/config/config/' out/bundle/sign_and_push.sh.tmp > out/bundle/sign_and_push.sh
	@chmod +x out/bundle/sign_and_push.sh
	@rm -f out/bundle/sign_and_push.sh.tmp
	@echo ">>> Bundle for local signing is created! <<<"
