-include ../.config
-include ../tools/config.mk
-include ../options.mk
-include ./wcs/pkcs11.mk

WOLFBOOT_LIB_WOLFSSL?=../lib/wolfssl
WOLFBOOT_LIB_WOLFTPM?=../lib/wolfTPM
WOLFBOOT_LIB_WOLFHSM?=../lib/wolfHSM
WOLFBOOT_LIB_WOLFIP?=../lib/wolfip
WOLFSSL_LOCAL_OBJDIR?=wolfssl_obj
WOLFTPM_LOCAL_OBJDIR?=wolftpm_obj
WOLFHSM_LOCAL_OBJDIR?=wolfhsm_obj
WOLFIP_LOCAL_OBJDIR?=wolfip_obj
vpath %.c $(WOLFBOOT_LIB_WOLFSSL)
vpath %.S $(WOLFBOOT_LIB_WOLFSSL)
vpath %.c $(WOLFBOOT_LIB_WOLFTPM)
vpath %.S $(WOLFBOOT_LIB_WOLFTPM)
vpath %.c $(WOLFBOOT_LIB_WOLFHSM)
vpath %.S $(WOLFBOOT_LIB_WOLFHSM)
vpath %.c $(WOLFBOOT_LIB_WOLFIP)

WOLFBOOT_ROOT?=..
TARGET?=none
ARCH?=ARM

# PPC64 (e5500/e6500) vs 32-bit (e500/e500mc), set early so the wolfCrypt asm
# wiring below sees it; per-TARGET blocks later re-assert the same value.
ifeq ($(ARCH),PPC)
  ifneq ($(filter nxp_t2080 nxp_t1024 nxp_t1040,$(TARGET)),)
    PPC64=1
  else
    PPC64=0
  endif
endif
MCUXPRESSO_CMSIS?=$(MCUXPRESSO)/CMSIS
ifneq (,$(filter $(TARGET),mcxa mcxw mcxn))
  ifneq ($(WOLFCRYPT_TZ_PSA),1)
    TEST_APP_NO_RNG?=1
  endif
endif
ifeq ($(TZEN),1)
  # wcs directory contains a user_settings.h, which will conflict with
  # the one in the include directory if the test app needs it (e.g. wolfHSM)
  CFLAGS:=-I./wcs $(CFLAGS)
endif
CFLAGS+=-I. -I..
DEBUG?=1
DELTA_DATA_SIZE?=2000
USE_CLANG?=0
ifeq ($(USE_CLANG),1)
  USE_GCC?=0
else
  USE_GCC?=1
endif
USE_GCC_HEADLESS?=1
BOOTLOADER_PARTITION_SIZE?=$$(( $(WOLFBOOT_PARTITION_BOOT_ADDRESS) - $(ARCH_FLASH_OFFSET)))

# For test-applications we should only use user_settings.h
CFLAGS+=-DWOLFSSL_USER_SETTINGS -DWOLFTPM_USER_SETTINGS

ifeq ($(WOLFBOOT_ATTESTATION_TEST),1)
  CFLAGS+=-DWOLFBOOT_ATTESTATION_TEST
endif

ifeq ($(HASH),SHA256)
  WOLFCRYPT_OBJS+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/sha256.o
  CFLAGS+=-D"WOLFBOOT_HASH_SHA256"
endif

ifeq ($(NVM_FLASH_WRITEONCE),1)
  CFLAGS+=-D"NVM_FLASH_WRITEONCE"
endif


ifeq ($(HASH),SHA3_384)
  WOLFCRYPT_OBJS+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/sha3.o
  CFLAGS+=-D"WOLFBOOT_HASH_SHA3_384"
endif

STACK_USAGE_LIMIT:=1024
ifeq ($(TARGET),sim)
  STACK_USAGE_LIMIT:=4608
endif

ifeq ($(TARGET),ti_hercules)
  APP_OBJS:=app_$(TARGET).o ../test-app/libwolfboot.o
  CFLAGS+=-I"../include"
else
  CFLAGS+=-Wall -ffreestanding -Wno-unused -ffunction-sections -fdata-sections
  # Stack usage computation not supported on TriCore
  ifneq ($(ARCH),AURIX_TC3)
    ifneq ($(USE_CLANG),1)
      CFLAGS+=-Wstack-usage=$(STACK_USAGE_LIMIT)
    endif
  endif
  CFLAGS+=-DTARGET_$(TARGET) -I../include
  CFLAGS+=-g
  ifeq ($(USE_GCC),1)
    CFLAGS+=-ggdb3
  else ifneq ($(ARCH),AURIX_TC3)
    ifneq ($(USE_CLANG),1)
      # -gstabs was removed in GCC 12; -gdwarf-4 works on old and new GCC
      CFLAGS+=-gdwarf-4
    endif
  endif

  ifeq ($(ARCH),RENESAS_RX)
    APP_OBJS:=app_renesas_rx.o ../test-app/libwolfboot.o ../src/boot_renesas.o ../src/boot_renesas_start.o ../hal/renesas-rx.o
    # -ffreestanding/-nostartfiles are gcc-driver flags. Only pass them when
    # linking via gcc (USE_GCC=1); for USE_GCC=0 rx-elf-ld is invoked directly
    # and rejects them (-ffreestanding is already in CFLAGS; ld adds no crt).
    ifeq ($(USE_GCC),1)
      LDFLAGS+=-ffreestanding -nostartfiles
    endif
    CFLAGS+=-DWOLFBOOT_RENESAS_APP
  else ifeq ($(WOLFHAL),1)
    APP_OBJS:=app_wolfhal.o led.o system.o timer.o ../test-app/libwolfboot.o
  else
    APP_OBJS:=app_$(TARGET).o led.o system.o timer.o ../test-app/libwolfboot.o
  endif
endif

# Disable Thumb2 ASM for MAX32666 before arch.mk: hardware TPU handles AES
ifeq ($(TARGET),max32666)
  ifeq ($(WOLFCRYPT_MAX32666_TEST),1)
    NO_ARM_ASM=1
  endif
endif

include ../arch.mk

# The Renesas RX app links with ld directly (USE_GCC=0), with no gcc driver to
# pull in newlib. syscalls.o provides a minimal stdio (printf/putchar/snprintf/
# malloc) on top of uart_write, so the app links without libc.
ifeq ($(ARCH),RENESAS_RX)
  APP_OBJS+=syscalls.o
endif

ifeq ($(USE_CLANG),1)
  APP_NEEDS_STRING:=1
endif

# Optional alias for clearer TZ PSA selection in app builds.
ifeq ($(WOLFCRYPT_TZ_PSA),1)
  WOLFCRYPT_TZ=1
  WOLFCRYPT_TZ_PSA=1
endif

ifeq ($(WOLFCRYPT_TZ_FWTPM),1)
  WOLFCRYPT_TZ=1
  WOLFCRYPT_TZ_FWTPM=1
endif

ifeq ($(WOLFCRYPT_TZ_WOLFHSM),1)
  WOLFCRYPT_TZ=1
  WOLFCRYPT_TZ_WOLFHSM=1
endif

# Setup default linker flags (gcc-driver form). Renesas RX links with ld
# directly (USE_GCC=0) and gets its -T/-gc-sections/oformat from arch.mk, so
# these gcc-driver flags (-Wl,/-nostartfiles and a duplicate -T) are skipped.
ifneq ($(ARCH),RENESAS_RX)
LDFLAGS+=-T $(LSCRIPT) -Wl,-gc-sections -Wl,-Map=image.map -nostartfiles
endif

# Setup default objcopy flags
OBJCOPY_FLAGS+=--gap-fill $(FILL_BYTE)

ifeq ($(USE_CLANG),1)
  APP_OBJS+=../src/clang_sections.o
endif

ifeq ($(DEBUG_UART),1)
    CFLAGS+=-DDEBUG_UART
    APP_NEEDS_STRING:=1
endif

ifeq ($(ARCH),AURIX_TC3)
# AURIX RAM_CODE HAL flash drivers need wolfBoot memcpy
    APP_NEEDS_STRING:=1
endif

ifeq ($(APP_NEEDS_STRING),1)
    APP_OBJS+=../src/string.o
endif

# wolfCrypt Test and Benchmark Support
WOLFCRYPT_SUPPORT=0

# MAX32666 hardware crypto test (MSDK TPU/MAA/TRNG acceleration)
# Base TPU/SHA support and MSDK paths are inherited from arch.mk
# when MAX3266X_TPU=1. This block adds the extra features for the
# full crypto test (AES, RNG, MAA math, ECDHE).
ifeq ($(TARGET),max32666)
  ifeq ($(WOLFCRYPT_MAX32666_TEST),1)
    STACK_USAGE_LIMIT:=5200
    CFLAGS += -DWOLFCRYPT_MAX32666_TEST
    CFLAGS += -DMAX3266X_RNG -DMAX3266X_AES -DMAX3266X_MATH
    CFLAGS += -DHAVE_ECC_CDH -DHAVE_ECC_DHE
    CFLAGS += -DHAVE_AESGCM -DGCM_TABLE
    CFLAGS += -DENCRYPT_WITH_AES256
    CFLAGS += -DWOLFSSL_SP_MATH_ALL
    CFLAGS += -I$(MSDK_DIR)/Libraries/PeriphDrivers/Source/TRNG/
    WOLFCRYPT_SUPPORT=1
  endif
endif

ifeq ($(WOLFCRYPT_TEST),1)
  CFLAGS+=-DWOLFCRYPT_TEST
  WOLFCRYPT_SUPPORT=1
  APP_OBJS+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/test/test.o
endif

ifeq ($(WOLFCRYPT_BENCHMARK),1)
  CFLAGS+=-DWOLFCRYPT_BENCHMARK
  WOLFCRYPT_SUPPORT=1
  UART_PRINTF_FLOAT?=1
  APP_OBJS+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/benchmark/benchmark.o
endif

ifeq ($(UART_PRINTF_FLOAT),1)
  CFLAGS+=-DUART_PRINTF_FLOAT
endif

ifeq ($(WOLFCRYPT_SUPPORT),1)
  # Add support infrastructure
  APP_OBJS+=wolfcrypt_support.o
  APP_OBJS+=syscalls.o

  # Add wolfCrypt core implementation files
  APP_OBJS+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/hash.o
  APP_OBJS+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/wc_port.o
  APP_OBJS+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/logging.o
  APP_OBJS+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/misc.o
  APP_OBJS+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/wolfmath.o
  APP_OBJS+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/memory.o
  APP_OBJS+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/asn.o
  APP_OBJS+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/coding.o
  APP_OBJS+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/wc_encrypt.o

  # Add SHA implementations (needed for test/benchmark)
  APP_OBJS+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/sha256.o
  APP_OBJS+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/sha512.o
  APP_OBJS+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/sha3.o
  APP_OBJS+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/hmac.o

  # Add RNG support (needed for ECC signing and tests)
  APP_OBJS+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/random.o

  # Add AES support (needed by benchmark for AES-CBC etc.)
  APP_OBJS+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/aes.o

  # Add ECC support (needed by test suite)
  APP_OBJS+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/ecc.o
  APP_OBJS+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/sp_int.o

  # Add SP C math (sp_c64 for 64-bit RISC-V, sp_c32 otherwise)
  ifeq ($(ARCH),RISCV64)
    APP_OBJS+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/sp_c64.o
  else
    APP_OBJS+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/sp_c32.o
  endif

  # Add RSA support
  APP_OBJS+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/rsa.o

  ifneq ($(NO_ASM),1)
    # SP Cortex M
    ifneq ($(filter ARM ARM_BE,$(ARCH)),)
      ifeq ($(SPMATH),1)
        APP_OBJS+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/sp_cortexm.o
      endif

      ifneq ($(NO_ARM_ASM),1)
        APP_OBJS+= \
              $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/port/arm/thumb2-aes-asm_c.o \
              $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/port/arm/thumb2-sha256-asm_c.o \
              $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/port/arm/thumb2-sha512-asm_c.o \
              $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/port/arm/thumb2-sha3-asm_c.o \
              $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/port/arm/thumb2-chacha-asm_c.o

        CFLAGS+=-DWOLFSSL_ARMASM -DWOLFSSL_ARMASM_NO_HW_CRYPTO -DWOLFSSL_ARMASM_INLINE \
                -DWOLFSSL_ARMASM_NO_NEON -DWOLFSSL_ARMASM_THUMB2
      endif
    endif

    # Power PC (wolfSSL PRs 10740 + 10767: AES/SHA-2/SHA-3 PPC asm)
    ifeq ($(ARCH),PPC)
      # SP big-number math stays on the 32-bit PPC asm path (matches the
      # bootloader and the SP_WORD_SIZE=32 user_settings.h forces for PPC); the
      # AES/SHA asm under test is independent of SP math.
      CFLAGS+=-DWOLFSSL_SP_PPC
      # PPC_ASM=0 builds wolfCrypt pure-C (no PPC64/PPC32 AES/SHA asm) for the
      # C-vs-asm benchmark baseline. Default on.
      PPC_ASM?=1
      ifeq ($(PPC_ASM),1)
      ifeq ($(PPC64),1)
        # e5500/e6500: PPC64 base-scalar ASM (AES T-table, SHA-2/SHA-3 via
        # 64-bit GPR ops). These are NOT POWER8 -- no VSX/vector-crypto -- so
        # WOLFSSL_PPC64_ASM_CRYPTO / _POWER8 must NOT be set (they emit
        # vcipher/vshasigma and would trap).
        CFLAGS+=-DWOLFSSL_PPC64_ASM
        CFLAGS+=-DWOLFSSL_PPC64_ASM_INLINE
        CFLAGS+=-DWOLFSSL_PPC64_ASM_SMALL
        CFLAGS+=-DWOLFSSL_PPC64_ASM_AES_NO_HARDEN
        APP_OBJS+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/port/ppc64/ppc64-aes-asm_c.o
        APP_OBJS+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/port/ppc64/ppc64-sha256-asm_c.o
        APP_OBJS+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/port/ppc64/ppc64-sha512-asm_c.o
        APP_OBJS+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/port/ppc64/ppc64-sha3-asm_c.o
      else
        # e500mc: PPC32 base-scalar ASM, condition-register variant (PR 10740).
        # INLINE_REG selects the *_cr.c files and needs the assembler to accept
        # symbolic register names (-Wa,-mregnames).
        CFLAGS+=-DWOLFSSL_PPC32_ASM
        CFLAGS+=-DWOLFSSL_PPC32_ASM_INLINE
        CFLAGS+=-DWOLFSSL_PPC32_ASM_INLINE_REG -Wa,-mregnames
        CFLAGS+=-DWOLFSSL_PPC32_ASM_SMALL
        APP_OBJS+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/port/ppc32/ppc32-aes-asm_cr.o
        APP_OBJS+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/port/ppc32/ppc32-sha256-asm_cr.o
        APP_OBJS+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/port/ppc32/ppc32-sha512-asm_cr.o
        APP_OBJS+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/port/ppc32/ppc32-sha3-asm_cr.o
      endif
      endif  # PPC_ASM

      CFLAGS+=-fomit-frame-pointer
    endif

    # AArch64 (ARMv8): armv8 asm + SP arm64 objects (as arch.mk links for the
    # bootloader). The test-app is a separate link with full AES/SHA/ECC under
    # WOLFSSL_ARMASM (and the __aarch64__ SP asm in user_settings.h).
    ifeq ($(ARCH),AARCH64)
      ifneq ($(NO_ARM_ASM),1)
        ifeq ($(SPMATH),1)
          APP_OBJS+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/sp_arm64.o
        endif
        APP_OBJS+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/cpuid.o \
                  $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/port/arm/armv8-aes-asm_c.o \
                  $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/port/arm/armv8-sha256-asm_c.o \
                  $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/port/arm/armv8-sha512-asm_c.o \
                  $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/port/arm/armv8-sha3-asm_c.o
        # armv8 asm uses crypto mnemonics (aese/sha256h); arch.mk's +crypto is
        # lost to a later -mstrict-align, so restore it here for the asm.
        CFLAGS+=-march=armv8-a+crypto
        # libgcc for SP math 128-bit helpers (__udivti3); link is -nodefaultlibs.
        LIBS+=-lgcc
        # syscalls.c _sbrk references _Min_Heap_Size; no heap, so anchor it at
        # zero (ARM does the same).
        LDFLAGS+=-Wl,--defsym=_Min_Heap_Size=0
      endif
    endif

    # RISC-V 64-bit (mirrors the WOLFCRYPT_OBJS asm set in arch.mk).
    # arch.mk already adds -DWOLFSSL_RISCV_ASM to CFLAGS for the app, so the
    # wolfcrypt C sources expect these asm symbols; provide the objects here.
    ifeq ($(ARCH),RISCV64)
      CFLAGS+=-DWOLFSSL_RISCV_ASM
      APP_OBJS+= \
            $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/port/riscv/riscv-64-sha256.o \
            $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/port/riscv/riscv-64-sha512.o \
            $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/port/riscv/riscv-64-sha3.o \
            $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/port/riscv/riscv-64-aes.o
    endif
  endif

  CFLAGS+=-DWOLFSSL_USER_SETTINGS
  CFLAGS+=-I"$(WOLFBOOT_LIB_WOLFSSL)"
endif # WOLFCRYPT_SUPPORT

ifeq ($(TZEN),1)
    CFLAGS+=-DNONSECURE_APP
    CFLAGS+=-I./
    APP_OBJS+=../hal/$(TARGET)_ns.o
    APP_OBJS+=../src/wolfboot_tz_nsc.o
    ifeq ($(WOLFCRYPT_TZ),1)
        CFLAGS+=-I"$(WOLFBOOT_LIB_WOLFSSL)"
        WOLFCRYPT_APP_OBJS+=\
            $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/memory.o \
            $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/hash.o \
            $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/sha.o \
            $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/sha256.o \
            $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/sha512.o \
            $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/sha3.o \
            $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/hmac.o \
            $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/pwdbased.o \
            $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/pkcs12.o \
            $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/coding.o \
            $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/asn.o \
            $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/ecc.o \
            $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/rsa.o \
            $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/aes.o \
            $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/wolfmath.o \
            $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/sp_int.o \
            $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/sp_cortexm.o \
            $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/sp_c32.o \
            $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/wc_port.o \
            $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/wolfentropy.o \
            $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/dh.o \
            $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/wc_encrypt.o
        ifeq ($(WOLFCRYPT_TZ_PKCS11),1)
            CFLAGS+=-DWOLFSSL_USER_SETTINGS -DWOLFTPM_USER_SETTINGS
            CFLAGS+=-DWOLFBOOT_PKCS11_APP -DSECURE_PKCS11 -DWOLFBOOT_TZ_PKCS11
            ifeq ($(PKCS11_TESTAPP),1)
                CFLAGS+=-DWOLFBOOT_PKCS11_TESTAPP
            endif
            CFLAGS+=-I"$(WOLFBOOT_LIB_WOLFPKCS11)"
            APP_OBJS+=./test_pkcs11.o
            APP_OBJS+=./wcs/pkcs11_stub.o
            APP_OBJS+=./wcs/ecc.o
            APP_OBJS+=./wcs/rsa.o
            APP_OBJS+=./wcs/asn.o
            APP_OBJS+=./wcs/aes.o
            APP_OBJS+=./wcs/hmac.o
            APP_OBJS+=./wcs/pwdbased.o
            APP_OBJS+=./wcs/pkcs12.o
            APP_OBJS+=./wcs/hash.o
            APP_OBJS+=./wcs/sha256.o
            APP_OBJS+=./wcs/sha512.o
            APP_OBJS+=./wcs/sha3.o
            APP_OBJS+=./wcs/integer.o
            APP_OBJS+=./wcs/tfm.o
            APP_OBJS+=./wcs/sp_c32.o
            APP_OBJS+=./wcs/sp_int.o
            APP_OBJS+=./wcs/cryptocb.o
            APP_OBJS+=./wcs/wc_pkcs11.o
            APP_OBJS+=./wcs/memory.o
            APP_OBJS+=./wcs/wolfmath.o
            APP_OBJS+=./wcs/dh.o
            APP_OBJS+=./wcs/random.o
            APP_OBJS+=./wcs/coding.o
            APP_OBJS+=./wcs/wc_encrypt.o
            APP_OBJS+=./wcs/wc_port.o
            ifeq ($(SIGN),LMS)
                APP_OBJS+=./wcs/wc_lms.o
                APP_OBJS+=./wcs/wc_lms_impl.o
            endif
            ifeq ($(SIGN),XMSS)
                APP_OBJS+=./wcs/wc_xmss.o
                APP_OBJS+=./wcs/wc_xmss_impl.o
            endif
            ifeq ($(SIGN),ML_DSA)
                APP_OBJS+=./wcs/wc_mldsa.o
            endif

            ifeq ($(SPMATH),1)
              CFLAGS+=-DWOLFSSL_HAVE_SP_RSA -DWOLFSSL_HAVE_SP_ECC
              ifneq ($(NO_ASM),1)
                CFLAGS+=-fomit-frame-pointer # required with debug builds only
                CFLAGS+=-DWOLFSSL_SP_ARM_CORTEX_M_ASM
                APP_OBJS+=./wcs/sp_cortexm.o
              endif
            endif
        else
            ifeq ($(TEST_APP_NO_RNG),1)
                CFLAGS+=-DWC_NO_RNG
            else
                WOLFCRYPT_APP_OBJS+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/random.o
            endif
        endif
        CFLAGS+=-DWOLFBOOT_SECURE_CALLS
        ifneq ($(USE_CLANG),1)
          CFLAGS+=-Wstack-usage=19184
          LDFLAGS+=--specs=nosys.specs
        endif
        LDFLAGS+=-u _printf_float
    endif
    ifeq ($(WOLFCRYPT_TZ_PSA),1)
        CFLAGS+=-DWOLFCRYPT_TZ_PSA -DWOLFSSL_HAVE_PSA
        CFLAGS+=-I../zephyr/include -I../lib/wolfPSA/wolfpsa
        CFLAGS+=-I"$(WOLFBOOT_LIB_WOLFSSL)" -I"$(WOLFBOOT_LIB_WOLFSSL)/wolfssl"
        APP_OBJS+=hal_trng_psa.o
        APP_OBJS+=../zephyr/src/wolfboot_psa_ns_api.o
        APP_OBJS+=arm_tee_ns_interface_stub.o
        APP_OBJS+=../zephyr/src/arm_tee_attest_api.o
        APP_OBJS+=../zephyr/src/arm_tee_crypto_api.o
        WOLFCRYPT_APP_OBJS+=\
            $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/port/psa/psa.o \
            $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/port/psa/psa_aes.o \
            $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/port/psa/psa_hash.o \
            $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/port/psa/psa_pkcbs.o
    endif
    ifeq ($(WOLFCRYPT_TZ_FWTPM),1)
        CFLAGS:=$(filter-out -DWOLFTPM_FWTPM,$(CFLAGS))
        CFLAGS+=-DWOLFBOOT_TZ_FWTPM -DWOLFBOOT_TPM -DWOLFTPM_ADV_IO
        CFLAGS+=-DWOLFTPM_EXAMPLE_HAL
        CFLAGS+=-I"$(WOLFBOOT_LIB_WOLFTPM)"
        APP_OBJS+=./wcs/fwtpm_stub.o
        WOLFTPM_APP_OBJS+=\
            $(WOLFBOOT_LIB_WOLFTPM)/src/tpm2.o \
            $(WOLFBOOT_LIB_WOLFTPM)/src/tpm2_packet.o \
            $(WOLFBOOT_LIB_WOLFTPM)/src/tpm2_tis.o \
            $(WOLFBOOT_LIB_WOLFTPM)/src/tpm2_wrap.o \
            $(WOLFBOOT_LIB_WOLFTPM)/src/tpm2_param_enc.o \
            $(WOLFBOOT_LIB_WOLFTPM)/src/tpm2_util.o \
            $(WOLFBOOT_LIB_WOLFTPM)/src/tpm2_crypto.o
        WOLFTPM_APP_OBJS := $(patsubst $(WOLFBOOT_LIB_WOLFTPM)/%, \
            $(WOLFTPM_LOCAL_OBJDIR)/%, $(WOLFTPM_APP_OBJS))
        APP_OBJS+=$(sort $(WOLFTPM_APP_OBJS))
    endif
    ifeq ($(WOLFCRYPT_TZ_WOLFHSM),1)
        CFLAGS+=-DWOLFCRYPT_TZ_WOLFHSM
        CFLAGS+=-DWOLFHSM_CFG_ENABLE_CLIENT
        CFLAGS+=-DWOLFHSM_CFG_COMM_DATA_LEN=1280
        CFLAGS+=-DWOLFHSM_CFG_PORT_ARMV8M_TZ_NSC
        CFLAGS+=-DWOLFHSM_CFG_NO_SYS_TIME
        ifeq ($(WOLFBOOT_TZ_TEST_BKPT),1)
            CFLAGS+=-DWOLFBOOT_TZ_TEST_BKPT
        endif
        CFLAGS+=-I"$(WOLFBOOT_LIB_WOLFHSM)"
        CFLAGS+=-I"$(WOLFBOOT_LIB_WOLFHSM)/port/armv8m-tz"
        CFLAGS+=-I"$(WOLFBOOT_LIB_WOLFHSM)/test"
        WOLFCRYPT_APP_OBJS+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/cryptocb.o
        APP_OBJS+=./wcs/wolfhsm_test.o
        APP_OBJS+=./wcs/wolfhsm_stub.o
        WOLFHSM_APP_OBJS+=$(WOLFHSM_CLIENT_OBJS)
        WOLFHSM_APP_OBJS+=$(WOLFBOOT_LIB_WOLFHSM)/port/armv8m-tz/wh_transport_nsc.o
        # wolfHSM bare-metal-safe test sources for whTest_ClientConfig.
        # We avoid wh_test.c (has its own main()) and wh_test_common.c (its
        # static whNvmCb table pulls in server-side wh_NvmFlash_* symbols
        # that don't belong in the NS image). The remaining files compile
        # cleanly under WOLFHSM_CFG_ENABLE_CLIENT only.
        WOLFHSM_APP_OBJS+=$(WOLFBOOT_LIB_WOLFHSM)/test/wh_test_clientserver.o
        WOLFHSM_APP_OBJS+=$(WOLFBOOT_LIB_WOLFHSM)/test/wh_test_crypto.o
        WOLFHSM_APP_OBJS+=$(WOLFBOOT_LIB_WOLFHSM)/test/wh_test_nvmflags.o
        WOLFHSM_APP_OBJS:=$(patsubst $(WOLFBOOT_LIB_WOLFHSM)/%, \
            $(WOLFHSM_LOCAL_OBJDIR)/%, $(WOLFHSM_APP_OBJS))
        APP_OBJS+=$(sort $(WOLFHSM_APP_OBJS))
    endif
    WOLFCRYPT_APP_OBJS := $(patsubst $(WOLFBOOT_LIB_WOLFSSL)/%, \
        $(WOLFSSL_LOCAL_OBJDIR)/%, $(WOLFCRYPT_APP_OBJS))
    ifneq ($(WOLFCRYPT_TZ_PKCS11),1)
        APP_OBJS+=$(sort $(WOLFCRYPT_APP_OBJS))
    endif
else
    ifeq ($(WOLFHAL),1)
        APP_OBJS+=../hal/wolfhal.o
    else
        APP_OBJS+=../hal/$(TARGET).o
    endif
endif

ifeq ($(ARCH),RISCV)
  APP_OBJS+=startup_riscv.o vector_riscv.o
endif

ifeq ($(ARCH),AARCH64)
  APP_OBJS:=boot_arm64_start.o $(APP_OBJS)
  # Prevent inclusion of standard C runtime startup files that conflict with boot_arm64_start.S
  # Use -Wl, prefix to pass flags directly to linker when GCC is used as linker driver
  LDFLAGS+=-nostartfiles -nostdlib -nodefaultlibs -Wl,--entry=_start
endif

ifeq ($(ARCH),RISCV64)
  APP_OBJS+=startup_riscv.o vector_riscv.o
endif

ifeq ($(ARCH),ARM)
  APP_OBJS+=startup_arm.o
endif
ifeq ($(ARCH),ARM_BE)
  APP_OBJS+=startup_arm.o
  CFLAGS+=-DSTACK_PAINTING=0
endif

ifeq ($(ENCRYPT),1)
    CFLAGS+=-D"EXT_ENCRYPTED=1"
endif

ENTRY_POINT=`cat .entry-point-address`
LSCRIPT:=../config/target-app.ld
LSCRIPT_TEMPLATE:=$(ARCH).ld

ifeq ($(TARGET),stm32f7)
  LSCRIPT_TEMPLATE=ARM-stm32f7.ld
  CFLAGS+=-DDUALBANK_SWAP
endif

ifeq ($(TARGET),stm32h7)
  LSCRIPT_TEMPLATE=ARM-stm32h7.ld
endif

ifeq ($(TARGET),stm32c0)
  LSCRIPT_TEMPLATE=ARM-stm32c0.ld
endif

ifeq ($(TARGET),sama5d3)
  APP_OBJS+=./boot_arm32_start.o
  LSCRIPT_TEMPLATE:=$(ARCH)-$(TARGET).ld
endif

ifeq ($(TARGET),zynq7000)
  APP_OBJS+=./boot_arm32_start.o
  LSCRIPT_TEMPLATE:=$(ARCH)-$(TARGET).ld
endif

ifeq ($(TARGET),stm32l4)
  APP_OBJS+=$(STM32CUBE)/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_flash.o
  APP_OBJS+=$(STM32CUBE)/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_flash_ex.o
  CFLAGS+=-DSTM32L4A6xx -DUSE_HAL_DRIVER -I../src -I../hal \
    -I$(STM32CUBE)/Drivers/STM32L4xx_HAL_Driver/Inc/ \
    -I$(STM32CUBE)/Drivers/BSP/STM32L4xx_Nucleo_144/ \
    -I$(STM32CUBE)/Drivers/CMSIS/Device/ST/STM32L4xx/Include/ \
    -I$(STM32CUBE)/Drivers/CMSIS/Include/
endif

ifeq ($(TARGET),stm32l5)
  ifeq ($(TZEN),1)
    LSCRIPT_TEMPLATE=ARM-stm32l5-ns.ld
    APP_OBJS+=wcs/wolfcrypt_secure.o
  else
    LSCRIPT_TEMPLATE=ARM-stm32l5.ld
  endif
  CFLAGS+=-mcpu=cortex-m33 -ffunction-sections -fdata-sections -fno-common
  LDFLAGS+=-mcpu=cortex-m33
  LDFLAGS+=-Wl,-gc-sections -Wl,-Map=image.map
  CFLAGS+=-I..
  APP_OBJS+=../hal/uart/uart_drv_$(UART_TARGET).o
endif

# i.MX95 Cortex-M7. The console is a shared-memory ring buffer rather than an
# LPUART: no M7 UART is routed to a host-accessible channel on the Toradex SMARC
# carrier, and Linux owns all four LPUART instances. -mcpu/-mfpu come from
# arch.mk via CORTEX_M7.
ifeq ($(TARGET),imx95_m7)
  CFLAGS+=-I..
  # The app owns isr_systick: it samples the DWT cycle counter often enough
  # that the 32-bit counter cannot wrap unnoticed between timebase reads.
  CFLAGS+=-DAPP_HAS_SYSTICK
  APP_OBJS+=../hal/uart/uart_drv_$(UART_TARGET).o
  LSCRIPT_TEMPLATE=ARM-imx95_m7.ld
endif

ifeq ($(TARGET),stm32h5)
  ifeq ($(TZEN),1)
    LSCRIPT_TEMPLATE=ARM-stm32h5-ns.ld
    APP_OBJS+=wcs/wolfcrypt_secure.o
    ifeq ($(WOLFCRYPT_TZ),1)
      APP_OBJS+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/logging.o
      APP_OBJS+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/test/test.o
      APP_OBJS+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/benchmark/benchmark.o
    endif
  else
    LSCRIPT_TEMPLATE=ARM-stm32h5.ld
  endif
  CFLAGS+=-DAPP_HAS_SYSTICK
  CFLAGS+=-DRAMFUNCTION='__attribute__((used,section(".ramcode"),long_call))'
  CFLAGS+=-mcpu=cortex-m33 -ffunction-sections -fdata-sections -fno-common
  CFLAGS+=-mlong-calls
  LDFLAGS+=-mcpu=cortex-m33
  LDFLAGS+=-Wl,-gc-sections -Wl,-Map=image.map
  CFLAGS+=-I..
  APP_OBJS+=../hal/uart/uart_drv_$(UART_TARGET).o
  ifneq ($(SIGN),NONE)
    ifeq ($(FLASH_OTP_KEYSTORE),1)
      APP_OBJS+=../src/flash_otp_keystore.o
    else
      APP_OBJS+=../src/keystore.o
    endif
  endif
endif

ifeq ($(TARGET),stm32n6)
  ifeq ($(TZEN),1)
    LSCRIPT_TEMPLATE=ARM-stm32n6-ns.ld
  else
    LSCRIPT_TEMPLATE=ARM-stm32n6.ld
  endif
  CFLAGS+=-mcpu=cortex-m55 -ffunction-sections -fdata-sections -fno-common
  # Suppress ARM EABI unwind tables. clang (unlike arm-none-eabi-gcc)
  # emits .ARM.exidx PREL31 entries for every function by default,
  # including the RAMFUNCTION-tagged helpers in libwolfboot.o that live
  # in the test-app's .ramcode (VMA in AXISRAM1 NS alias 0x2401xxxx,
  # LMA in XSPI2 NOR 0x7018xxxx). The FLASH-to-RAM VMA delta is
  # ~1.27 GB, which exceeds PREL31's signed ~1.07 GB range and lld
  # errors at link time. Bare-metal test-app has no use for unwind
  # tables; suppressing the generation keeps GCC and clang link
  # behavior identical.
  CFLAGS+=-fno-unwind-tables -fno-asynchronous-unwind-tables
  LDFLAGS+=-mcpu=cortex-m55
  LDFLAGS+=-Wl,-gc-sections -Wl,-Map=image.map
  CFLAGS+=-I..
endif

ifeq ($(TARGET),stm32u5)
  ifeq ($(TZEN),1)
    LSCRIPT_TEMPLATE=ARM-stm32u5-ns.ld
  else
    LSCRIPT_TEMPLATE=ARM-stm32u5.ld
  endif
  CFLAGS+=-mcpu=cortex-m33
  LDFLAGS+=-mcpu=cortex-m33
  ifeq ($(DEBUG_UART),1)
    APP_OBJS+=../hal/uart/uart_drv_$(UART_TARGET)_ns.o
  endif
endif

ifeq ($(TARGET),stm32u3)
  LSCRIPT_TEMPLATE=ARM-stm32u3.ld
  CFLAGS+=-mcpu=cortex-m33 -ffunction-sections -fdata-sections -fno-common
  LDFLAGS+=-mcpu=cortex-m33
  LDFLAGS+=-Wl,-gc-sections -Wl,-Map=image.map
  CFLAGS+=-I..
endif

ifeq ($(TARGET),stm32c5)
  LSCRIPT_TEMPLATE=ARM-stm32c5.ld
  CFLAGS+=-mcpu=cortex-m33 -ffunction-sections -fdata-sections -fno-common
  LDFLAGS+=-mcpu=cortex-m33
  LDFLAGS+=-Wl,-gc-sections -Wl,-Map=image.map
  CFLAGS+=-I..
endif

ifeq ($(TARGET),nrf5340)
  ifeq ($(TZEN),1)
    LSCRIPT_TEMPLATE=ARM-nrf5340-ns.ld
  else
    LSCRIPT_TEMPLATE=ARM.ld
  endif
endif

ifeq ($(TARGET),nrf54l)
  ifeq ($(TZEN),1)
    LSCRIPT_TEMPLATE=ARM-nrf54l-ns.ld
  else
    LSCRIPT_TEMPLATE=ARM.ld
  endif
endif

ifeq ($(TARGET),nrf5340_net)
  CFLAGS+=-mcpu=cortex-m33+nodsp+nofp
  LDFLAGS+=-mcpu=cortex-m33+nodsp+nofp
  LSCRIPT_TEMPLATE=ARM-nrf5340_net.ld
endif

ifeq ($(TARGET),max32666)
  LSCRIPT_TEMPLATE=ARM-max32666.ld
  ifeq ($(WOLFCRYPT_MAX32666_TEST),1)
    ifeq ($(MAX3266X_OLD),1)
      MAX3266X_SRC := $(MSDK_DIR)/Libraries/MAX32665PeriphDriver/Source
      APP_OBJS += $(MAX3266X_SRC)/hash.o
      APP_OBJS += $(MAX3266X_SRC)/cipher.o
      APP_OBJS += $(MAX3266X_SRC)/maa.o
      APP_OBJS += $(MAX3266X_SRC)/mem_utils.o
      APP_OBJS += $(MAX3266X_SRC)/trng.o
      APP_OBJS += $(MAX3266X_SRC)/mxc_sys.o
      APP_OBJS += $(MAX3266X_SRC)/mxc_delay.o
    else
      APP_OBJS += $(MSDK_DIR)/Libraries/PeriphDrivers/Source/TPU/tpu_me14.o
      APP_OBJS += $(MSDK_DIR)/Libraries/PeriphDrivers/Source/TPU/tpu_reva.o
      APP_OBJS += $(MSDK_DIR)/Libraries/PeriphDrivers/Source/TRNG/trng_reva.o
      APP_OBJS += $(MSDK_DIR)/Libraries/PeriphDrivers/Source/TRNG/trng_me14.o
      APP_OBJS += $(MSDK_DIR)/Libraries/PeriphDrivers/Source/TRNG/trng_revb.o
      APP_OBJS += $(MSDK_DIR)/Libraries/PeriphDrivers/Source/SYS/sys_me14.o
      APP_OBJS += $(MSDK_DIR)/Libraries/PeriphDrivers/Source/SYS/mxc_delay.o
    endif
    APP_OBJS += $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/port/maxim/max3266x.o
  endif
endif

ifeq ($(TARGET),ti_hercules)
  LSCRIPT_TEMPLATE=ARM-r5be.ld
  # Override linker flags
  LDFLAGS=--run_linker $(LSCRIPT) --map_file=image.map
  OBJCOPY_FLAGS=
endif

ifeq ($(TARGET),va416x0)
  APP_OBJS+=$(SDK_OBJS)
  LSCRIPT_TEMPLATE=ARM-va416x0.ld
  ifneq ($(SIGN),NONE)
    APP_OBJS+=../src/keystore.o
  endif
  # Reduce size: newlib-nano and section GC
  LDFLAGS+=--specs=nano.specs
  ifneq ($(WOLFCRYPT_SUPPORT),1)
    # Only use nosys stubs when not providing our own syscalls
    LDFLAGS+=--specs=nosys.specs
  endif
  ifeq ($(WOLFCRYPT_BENCHMARK),1)
    # Benchmark needs float printf for results
    LDFLAGS+=-u _printf_float
  endif
  CFLAGS+=-ffunction-sections -fdata-sections
endif

PPC64=0
ifeq ($(TARGET),nxp_t2080)
  ifneq ($(SIGN),NONE)
    APP_OBJS+=../src/keystore.o
  endif
  # PowerPC e6500
  PPC64=1
endif

ifeq ($(TARGET),nxp_t1024)
  ifneq ($(SIGN),NONE)
    APP_OBJS+=../src/keystore.o
  endif
  # PowerPC e5500
  PPC64=1
endif
ifeq ($(TARGET),nxp_t1040)
  ifneq ($(SIGN),NONE)
    APP_OBJS+=../src/keystore.o
  endif
  # PowerPC e5500
  PPC64=1
endif

ifeq ($(TARGET),sim)
  # LD on MacOS does not support "-Map="
  LDMAPSUPPORTED=$(shell $(CC) -Wl,-Map=image.map 2>&1 | grep 'unknown option')
  LDFLAGS=
  CFLAGS+=-fno-pie
  LDFLAGS+=-no-pie
  ifeq ($(FORCE_32BIT),1)
    LDFLAGS+=-m32
    CFLAGS+=-m32
  endif
  ifeq ($(LDMAPSUPPORTED),)
    # Override linker flags
    LDFLAGS+=-Wl,-Map=image.map
  endif
  ifeq ($(ELF_FLASH_SCATTER),1)
    LSCRIPT_TEMPLATE=sim_scattered.ld
    APP_OBJS=app_sim_scattered.o ../src/string.o
    CFLAGS+=-D"WOLFBOOT_ELF_FLASH_SCATTER=1" -nostartfiles -ffreestanding -static -nostdlib
    LDFLAGS+=-ffreestanding -nostartfiles -static -T$(LSCRIPT) -nostdlib
  else
    APP_OBJS=app_sim.o
    APP_OBJS+=../test-app/libwolfboot.o ../hal/$(TARGET).o
  endif
endif

# Self-header verification requires image.c (for verify_integrity/verify_authenticity)
# and keystore (for public key lookup), plus wolfcrypt for crypto operations
ifeq ($(WOLFBOOT_SELF_HEADER),1)
  CFLAGS+=-D"WOLFBOOT_SELF_HEADER"
  CFLAGS+=-I"$(WOLFBOOT_LIB_WOLFSSL)"
  # Test app needs additional image, keystore, and crypto objects to do verification
  APP_OBJS+=../src/image.o ../src/keystore.o
  # Only add wolfcrypt objs if WOLFHSM blocks won't provide them
  ifeq ($(WOLFHSM_CLIENT)$(WOLFHSM_SERVER),)
    # remove duplicates for certain object files. Under FIPS the object list is a
    # curated, link-ORDER-sensitive boundary (wolfcrypt_first.o ... _last.o, for
    # the in-core integrity hash) with no duplicates, so it must NOT be $(sort)ed
    # - sorting would move first/last and break the hash boundary.
    ifeq ($(FIPS),1)
      APP_OBJS+=$(WOLFCRYPT_OBJS)
    else
      APP_OBJS+=$(sort $(WOLFCRYPT_OBJS))
    endif
  endif
endif

ifeq ($(EXT_FLASH),1)
  CFLAGS+=-D"EXT_FLASH=1" -D"PART_UPDATE_EXT=1"
  ifeq ($(NO_XIP),1)
    CFLAGS+=-D"PART_BOOT_EXT=1"
  endif
endif

ifeq ($(SPI_FLASH),1)
  CFLAGS+=-D"SPI_FLASH"
  APP_OBJS+=../src/spi_flash.o
  ifeq ($(ARCH),RENESAS_RX)
    APP_OBJS+=../hal/spi/spi_drv_renesas_rx.o
  else
    APP_OBJS+=../hal/spi/spi_drv_$(SPI_TARGET).o
  endif
endif

ifeq ($(OCTOSPI_FLASH),1)
  QSPI_FLASH = 1
  CFLAGS+=-D"OCTOSPI_FLASH"
endif

ifeq ($(QSPI_FLASH),1)
  CFLAGS+=-D"QSPI_FLASH"
  APP_OBJS+=../src/qspi_flash.o
  ifeq ($(ARCH),RENESAS_RX)
    APP_OBJS+=../hal/spi/spi_drv_renesas_rx.o
  else
    ifeq ($(TZEN),1)
      APP_OBJS+=../hal/spi/spi_drv_$(SPI_TARGET)_ns.o
    else
      APP_OBJS+=../hal/spi/spi_drv_$(SPI_TARGET).o
    endif
  endif
endif

ifeq ($(WOLFHAL),1)
  ifeq ($(strip $(BOARD)),)
    $(error WOLFHAL=1 requires BOARD to be set, e.g. BOARD=stm32wb_nucleo)
  endif
  ifeq ($(wildcard $(WOLFBOOT_ROOT)/hal/boards/$(BOARD)/board.mk),)
    $(error BOARD=$(BOARD) has no hal/boards/$(BOARD)/board.mk)
  endif
  WOLFHAL_ROOT?=$(WOLFBOOT_ROOT)/lib/wolfHAL
  CFLAGS+=-I$(WOLFHAL_ROOT) -DWHAL_CFG_NO_TIMEOUT -I$(WOLFBOOT_ROOT)/hal/boards/$(BOARD)
  DEBUG_UART=1
  APP_OBJS+=board_$(BOARD).o
  include $(WOLFBOOT_ROOT)/hal/boards/$(BOARD)/board.mk
endif

ifeq ($(UART_FLASH),1)
  CFLAGS+=-D"UART_FLASH=1"
  APP_OBJS+= ../src/uart_flash.o ../hal/uart/uart_drv_$(UART_TARGET).o
else ifeq ($(TARGET),stm32wb)
  # With WOLFHAL=1, hal/wolfhal.c + the wolfHAL UART driver provide
  # uart_write; the legacy driver would collide.
  ifneq ($(WOLFHAL),1)
    APP_OBJS+=../hal/uart/uart_drv_$(UART_TARGET).o
  endif
endif

ifeq ($(TARGET),kinetis)
  APP_OBJS+=$(MCUXPRESSO_DRIVERS)/drivers/fsl_clock.o
  ifeq ($(MCUXSDK),1)
    APP_OBJS+=\
      $(MCUXPRESSO)/drivers/flash/fsl_ftfx_flash.o \
      $(MCUXPRESSO)/drivers/flash/fsl_ftfx_cache.o \
      $(MCUXPRESSO)/drivers/flash/fsl_ftfx_controller.o
  else
    APP_OBJS+=\
      $(MCUXPRESSO_DRIVERS)/drivers/fsl_ftfx_flash.o \
      $(MCUXPRESSO_DRIVERS)/drivers/fsl_ftfx_cache.o \
      $(MCUXPRESSO_DRIVERS)/drivers/fsl_ftfx_controller.o
  endif
endif

ifeq ($(TARGET),kinetis_kl26)
  LSCRIPT_TEMPLATE=ARM-kinetis_kl26.ld
  APP_OBJS+=\
    $(MCUXPRESSO_DRIVERS)/drivers/fsl_clock.o \
    $(MCUXPRESSO_DRIVERS)/drivers/fsl_gpio.o \
    $(MCUXPRESSO_DRIVERS)/drivers/fsl_flash.o
  ifneq (,$(filter 1,$(DEBUG_UART) $(UART_FLASH)))
    APP_OBJS+=$(MCUXPRESSO_DRIVERS)/drivers/fsl_lpsci.o
  endif
  LDFLAGS+=--specs=nosys.specs
endif

ifeq ($(TARGET),mcxa)
    LSCRIPT_TEMPLATE=ARM-mcxa.ld
    APP_OBJS+=$(MCUXPRESSO_PROJECT_TEMPLATE)/clock_config.o
    APP_OBJS+=$(MCUXPRESSO_DRIVERS)/drivers/fsl_clock.o
    APP_OBJS+=$(MCUXPRESSO_DRIVERS)/drivers/fsl_reset.o
    APP_OBJS+=$(MCUXPRESSO)/drivers/gpio/fsl_gpio.o
    APP_OBJS+=$(MCUXPRESSO)/drivers/mcx_spc/fsl_spc.o
    LDFLAGS+=--specs=nosys.specs
endif

ifeq ($(TARGET),s32k1xx)
    LSCRIPT_TEMPLATE=ARM-s32k1xx.ld
    ifneq ($(SIGN),NONE)
        APP_OBJS+=../src/keystore.o
    endif
    CFLAGS+=-DAPP_HAS_SYSTICK
    CFLAGS+=-DRAM_CODE -DDEBUG_UART
endif

ifeq ($(TARGET),stm32n6)
    CFLAGS+=-DRAM_CODE -DDEBUG_UART
    APP_OBJS+=syscalls.o
endif

ifeq ($(TARGET),mcxw)
    ifeq ($(TZEN),1)
      LSCRIPT_TEMPLATE=ARM-mcxw-ns.ld
      CFLAGS:=$(filter-out -mcmse, $(CFLAGS))
    else
      LSCRIPT_TEMPLATE=ARM-mcxw.ld
    endif
    APP_OBJS+=$(MCUXPRESSO_DRIVERS)/drivers/fsl_clock.o
    APP_OBJS+=$(MCUXPRESSO)/drivers/gpio/fsl_gpio.o
    APP_OBJS+=$(MCUXPRESSO)/drivers/spc/fsl_spc.o
    APP_OBJS+=$(MCUXPRESSO_PROJECT_TEMPLATE)/clock_config.o
    APP_OBJS+=$(MCUXPRESSO)/drivers/ccm32k/fsl_ccm32k.o
    APP_OBJS+=$(MCUXPRESSO_DRIVERS)/drivers/romapi/fsl_romapi.o
    LDFLAGS+=--specs=nosys.specs
endif

ifeq ($(TARGET),mcxn)
    ifeq ($(TZEN),1)
      LSCRIPT_TEMPLATE=ARM-mcxn-ns.ld
      CFLAGS:=$(filter-out -mcmse, $(CFLAGS))
    else
      LSCRIPT_TEMPLATE=ARM-mcxn.ld
    endif
    APP_OBJS+=\
      $(MCUXPRESSO_PROJECT_TEMPLATE)/clock_config.o \
      $(MCUXPRESSO)/drivers/gpio/fsl_gpio.o \
      $(MCUXPRESSO)/drivers/lpflexcomm/fsl_lpflexcomm.o \
      $(MCUXPRESSO)/drivers/lpuart/fsl_lpuart.o \
      $(MCUXPRESSO_DRIVERS)/drivers/fsl_reset.o \
      $(MCUXPRESSO_DRIVERS)/drivers/fsl_clock.o \
      $(MCUXPRESSO_DRIVERS)/drivers/romapi/flash/src/fsl_flash.o
    ifeq (,$(findstring nosys.specs,$(LDFLAGS)))
      LDFLAGS+=--specs=nosys.specs
    endif
endif

ifeq ($(TARGET),lpc55s69)
    CFLAGS+=-ffunction-sections -fdata-sections
    CFLAGS+=-DWOLFSSL_NXP_RNG_1
    ifeq ($(TZEN),1)
      LSCRIPT_TEMPLATE=ARM-lpc55s69-ns.ld
      CFLAGS:=$(filter-out -mcmse, $(CFLAGS))
    else
      LSCRIPT_TEMPLATE=ARM-lpc55s69.ld
    endif
    APP_OBJS+=\
      $(MCUXPRESSO_PROJECT_TEMPLATE)/clock_config.o \
      $(MCUXPRESSO_DRIVERS)/drivers/fsl_clock.o \
      $(MCUXPRESSO_DRIVERS)/drivers/fsl_reset.o \
      $(MCUXPRESSO)/drivers/common/fsl_common_arm.o \
      $(MCUXPRESSO)/drivers/flexcomm/fsl_flexcomm.o \
      $(MCUXPRESSO)/drivers/flexcomm/usart/fsl_usart.o \
      $(MCUXPRESSO)/drivers/iap1/fsl_iap.o \
      $(MCUXPRESSO)/drivers/lpc_gpio/fsl_gpio.o \
      $(MCUXPRESSO)/drivers/rng_1/fsl_rng.o
    ifeq ($(PKA),1)
      CFLAGS+=-DWOLFSSL_NXP_LPC55S6X
      APP_OBJS+=\
        $(MCUXPRESSO)/drivers/casper/fsl_casper.o \
        $(MCUXPRESSO)/drivers/hashcrypt/fsl_hashcrypt.o \
        $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/port/nxp/casper_port.o \
        $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/port/nxp/hashcrypt_port.o
    endif
    ifeq ($(WOLFCRYPT_SUPPORT),1)
      LDFLAGS+=--specs=nano.specs
    endif
    ifeq ($(WOLFCRYPT_BENCHMARK),1)
      # Benchmark needs float printf for results
      LDFLAGS+=-Wl,-u_printf_float
    endif
    LDFLAGS+=-Wl,--no-warn-rwx-segments -Wl,--allow-multiple-definition
endif

ifeq ($(TARGET),nxp_lpc54s0xx)
    LSCRIPT_TEMPLATE=ARM-nxp_lpc54s0xx.ld
    # Enable RAMFUNCTION for test app (flash ops must run from RAM)
    CFLAGS+=-DRAM_CODE -D__WOLFBOOT
    # string.o provides RAMFUNCTION memcpy; already added when DEBUG_UART=1 (line ~108)
    ifeq ($(DEBUG_UART),)
      APP_OBJS+=../src/string.o
    endif
    # Use shared newlib syscall stubs (routes _write to uart_write)
    APP_OBJS+=syscalls.o
    LDFLAGS+=-Wl,--no-warn-rwx-segments
endif

ifeq ($(TARGET),imx_rt)
  LDFLAGS+=\
    -mcpu=cortex-m7 -Wall --specs=nosys.specs -fno-common -ffunction-sections -fdata-sections \
    -ffreestanding -fno-builtin -mthumb -mapcs -Xlinker --gc-sections -Xlinker -static -Xlinker -z \
    -Xlinker muldefs -Xlinker -Map=output.map -static -lm -lc -lnosys
  LSCRIPT_TEMPLATE=imx_rt.ld
  APP_OBJS+=\
    imx_rt_clock_config.o \
    $(MCUXPRESSO_DRIVERS)/drivers/fsl_clock.o \
    $(MCUXPRESSO)/components/uart/fsl_adapter_lpuart.o \
    $(MCUXPRESSO)/components/serial_manager/fsl_component_serial_manager.o \
    $(MCUXPRESSO)/components/lists/fsl_component_generic_list.o \
    $(MCUXPRESSO)/components/serial_manager/fsl_component_serial_port_uart.o \
    $(MCUXPRESSO)/components/flash/nor/flexspi/fsl_flexspi_nor_flash.o
  ifeq ($(MCUXSDK),1)
    APP_OBJS+=\
      $(MCUXPRESSO)/drivers/igpio/fsl_gpio.o \
      $(MCUXPRESSO)/drivers/cache/armv7-m7/fsl_cache.o \
      $(MCUXPRESSO)/drivers/common/fsl_common.o \
      $(MCUXPRESSO)/drivers/common/fsl_common_arm.o \
      $(MCUXPRESSO)/drivers/flexspi/fsl_flexspi.o \
      $(MCUXPRESSO)/drivers/lpuart/fsl_lpuart.o \
      $(MCUXPRESSO)/components/str/fsl_str.o \
      $(MCUXPRESSO)/components/debug_console/fsl_debug_console.o
  else
    APP_OBJS+=\
      $(MCUXPRESSO_DRIVERS)/drivers/fsl_gpio.o \
      $(MCUXPRESSO_DRIVERS)/drivers/fsl_cache.o \
      $(MCUXPRESSO_DRIVERS)/drivers/fsl_common.o \
      $(MCUXPRESSO_DRIVERS)/drivers/fsl_common_arm.o \
      $(MCUXPRESSO_DRIVERS)/drivers/fsl_flexspi.o \
      $(MCUXPRESSO_DRIVERS)/utilities/str/fsl_str.o \
      $(MCUXPRESSO_DRIVERS)/drivers/fsl_lpuart.o \
      $(MCUXPRESSO_DRIVERS)/utilities/debug_console/fsl_debug_console.o
  endif

  ifeq ($(MCUXPRESSO_CPU),MIMXRT1042XJM5B)
    ifeq ($(MCUXSDK),1)
      CFLAGS+=-I$(MCUXPRESSO)/examples/_boards/evkmimxrt1040/project_template \
              -I$(MCUXPRESSO)/examples/_boards/evkmimxrt1040/xip/
    else
      CFLAGS+=-I$(MCUXPRESSO_DRIVERS)/project_template/ \
              -I$(MCUXPRESSO)/boards/evkmimxrt1040/xip/
    endif
    APP_OBJS+=$(MCUXPRESSO_DRIVERS)/system_MIMXRT1042.o
  else ifeq ($(MCUXPRESSO_CPU),MIMXRT1052DVJ6B)
    ifeq ($(MCUXSDK),1)
      CFLAGS+=-I$(MCUXPRESSO)/examples/_boards/evkbimxrt1050/project_template \
              -I$(MCUXPRESSO)/examples/_boards/evkbimxrt1050/xip/
    else
      CFLAGS+=-I$(MCUXPRESSO_DRIVERS)/project_template/ \
              -I$(MCUXPRESSO)/boards/evkmimxrt1050/xip/
    endif
    APP_OBJS+=$(MCUXPRESSO_DRIVERS)/system_MIMXRT1052.o
  else
    ifeq ($(MCUXPRESSO_CPU),MIMXRT1062DVL6A)
      ifeq ($(MCUXSDK),1)
        CFLAGS+=-I$(MCUXPRESSO)/examples/_boards/evkmimxrt1060/project_template \
                -I$(MCUXPRESSO)/examples/_boards/evkmimxrt1060/xip/
      else
        CFLAGS+=-I$(MCUXPRESSO_DRIVERS)/project_template/ \
                -I$(MCUXPRESSO)/boards/evkmimxrt1060/xip/
      endif
      APP_OBJS+=$(MCUXPRESSO_DRIVERS)/system_MIMXRT1062.o
    endif
    ifeq ($(MCUXPRESSO_CPU),MIMXRT1062DVL6B)
      ifeq ($(MCUXSDK),1)
        CFLAGS+=-I$(MCUXPRESSO)/examples/_boards/evkbmimxrt1060/project_template \
                -I$(MCUXPRESSO)/examples/_boards/evkbmimxrt1060/xip/
      else
        CFLAGS+=-I$(MCUXPRESSO_DRIVERS)/project_template/ \
                -I$(MCUXPRESSO)/boards/evkbmimxrt1060/xip/
      endif
      APP_OBJS+=$(MCUXPRESSO_DRIVERS)/system_MIMXRT1062.o
    endif
    ifeq ($(MCUXPRESSO_CPU),MIMXRT1064DVL6A)
      ifeq ($(MCUXSDK),1)
        CFLAGS+=-I$(MCUXPRESSO)/examples/_boards/evkmimxrt1064/project_template \
                -I$(MCUXPRESSO)/examples/_boards/evkmimxrt1064/xip/
      else
        CFLAGS+=-I$(MCUXPRESSO_DRIVERS)/project_template/ \
                -I$(MCUXPRESSO)/boards/evkmimxrt1064/xip/
      endif
      APP_OBJS+=$(MCUXPRESSO_DRIVERS)/system_MIMXRT1064.o
    endif
  endif
endif

ifeq ($(TARGET),stm32g0)
  CFLAGS+=-DNVM_FLASH_WRITEONCE=1
endif
ifeq ($(TARGET),stm32g4)
  CFLAGS+=-DNVM_FLASH_WRITEONCE=1
  CFLAGS+=-I../hal
  LDFLAGS+=-Wl,-gc-sections
  # Test app uses printf via syscalls.o (routes _write -> uart_write).
  # syscalls.c references uart_write/uart_vprintf from string.o; string.o
  # is already pulled in when DEBUG_UART=1. Pull it in unconditionally so
  # printf is available even when DEBUG_UART is off.
  ifeq ($(DEBUG_UART),)
    APP_OBJS+=../src/string.o
  endif
  APP_OBJS+=syscalls.o
  # _Min_Heap_Size is consumed by syscalls.c _sbrk(); ARM.ld does not
  # define a heap, so anchor it at zero. _sbrk is gc'd when malloc is
  # unused, but the symbol must still resolve.
  LDFLAGS+=-Wl,--defsym=_Min_Heap_Size=0
endif
ifeq ($(TARGET),stm32c0)
  CFLAGS+=-DNVM_FLASH_WRITEONCE=1
endif
ifeq ($(TARGET),stm32c5)
  CFLAGS+=-DNVM_FLASH_WRITEONCE=1
endif

ifeq ($(TARGET),hifive1.freedom)
  CFLAGS+=-I$(FREEDOM_E_SDK)/freedom-metal/ -D__METAL_MACHINE_HEADER=\"$(FREEDOM_E_SDK)/bsp/sifive-hifive1/metal.h\"
  APP_OBJS+=$(FREEDOM_E_SDK)/freedom-metal/src/clock.o
  APP_OBJS+=$(FREEDOM_E_SDK)/freedom-metal/src/led.o
  APP_OBJS+=$(FREEDOM_E_SDK)/freedom-metal/src/cache.o
  APP_OBJS+=$(FREEDOM_E_SDK)/freedom-metal/src/cpu.o
  APP_OBJS+=$(FREEDOM_E_SDK)/freedom-metal/src/gpio.o
  APP_OBJS+=$(FREEDOM_E_SDK)/freedom-metal/src/interrupt.o
  APP_OBJS+=$(FREEDOM_E_SDK)/freedom-metal/src/uart.o
  APP_OBJS+=$(FREEDOM_E_SDK)/freedom-metal/src/tty.o
  APP_OBJS+=$(FREEDOM_E_SDK)/freedom-metal/src/spi.o
  APP_OBJS+=$(FREEDOM_E_SDK)/freedom-metal/src/shutdown.o
  APP_OBJS+=$(FREEDOM_E_SDK)/freedom-metal/src/timer.o
  APP_OBJS+=$(FREEDOM_E_SDK)/freedom-metal/src/drivers/sifive,fe310-g000,hfrosc.o
  APP_OBJS+=$(FREEDOM_E_SDK)/freedom-metal/src/drivers/sifive,fe310-g000,hfxosc.o
  APP_OBJS+=$(FREEDOM_E_SDK)/freedom-metal/src/drivers/sifive,fe310-g000,pll.o
  APP_OBJS+=$(FREEDOM_E_SDK)/freedom-metal/src/drivers/sifive,fe310-g000,prci.o
  APP_OBJS+=$(FREEDOM_E_SDK)/freedom-metal/src/drivers/sifive,spi0.o
  APP_OBJS+=$(FREEDOM_E_SDK)/freedom-metal/src/drivers/sifive,uart0.o
  APP_OBJS+=$(FREEDOM_E_SDK)/freedom-metal/src/drivers/sifive,global-external-interrupts0.o
  APP_OBJS+=$(FREEDOM_E_SDK)/freedom-metal/src/drivers/sifive,local-external-interrupts0.o
  APP_OBJS+=$(FREEDOM_E_SDK)/freedom-metal/src/drivers/sifive,gpio0.o
  APP_OBJS+=$(FREEDOM_E_SDK)/freedom-metal/src/drivers/sifive,gpio-leds.o
  APP_OBJS+=$(FREEDOM_E_SDK)/freedom-metal/src/drivers/riscv,clint0.o
  APP_OBJS+=$(FREEDOM_E_SDK)/freedom-metal/src/drivers/riscv,plic0.o
  APP_OBJS+=$(FREEDOM_E_SDK)/freedom-metal/src/drivers/riscv,cpu.o
  APP_OBJS+=$(FREEDOM_E_SDK)/freedom-metal/src/drivers/fixed-clock.o
endif

ifeq ($(TARGET),hifive1)
  CFLAGS+=-DRAMFUNCTION='__attribute__((used,section(".ramcode")))'
  APP_OBJS+=hifive1_write_page.o
endif

ifeq ($(TARGET),mpfs250)
  LSCRIPT_TEMPLATE:=RISCV64-mpfs250.ld
  CFLAGS+=-DRAMFUNCTION='__attribute__((used,section(".ramcode")))'
endif

# $(CYPRESS_PDL)/devices/templates/COMPONENT_MTB/COMPONENT_CM0P/system_psoc6_cm0plus.o

ifeq ($(TARGET),psoc6)
  LSCRIPT_TEMPLATE:=ARM-psoc6.ld
  APP_OBJS+= $(CYPRESS_PDL)/drivers/source/cy_gpio.o
  APP_OBJS+= $(CYPRESS_PDL)/drivers/source/cy_device.o
  CFLAGS+=-I$(CYPRESS_PDL)/drivers/include/
  CFLAGS+=-I$(CYPRESS_PDL)/devices/include
  CFLAGS+=-I$(CYPRESS_PDL)/cmsis/include
  CFLAGS+=-I$(CYPRESS_TARGET_LIB)
  CFLAGS+=-I$(CYPRESS_CORE_LIB)/include
  CFLAGS+=-I$(CYPRESS_PDL)/devices/include/ip
  CFLAGS+=-I$(CYPRESS_PDL)/devices/templates/COMPONENT_MTB
  CFLAGS+=-DCY8C624ABZI_D44
endif

ifeq ($(TARGET),x86_fsp_qemu)
  APP_OBJS:=app_$(TARGET).o ../hal/x86_uart.o ../src/x86/common.o ../src/string.o
  LSCRIPT_TEMPLATE:=x86_fsp.ld
  LDFLAGS=
endif

ifeq ($(TARGET),versal)
  LSCRIPT_TEMPLATE:=AARCH64.ld
  LDFLAGS+=-nostdlib
  # Enable DEBUG_UART for test-app to use wolfBoot_printf and hal functions
  DEBUG_UART:=1
  CFLAGS+=-DDEBUG_UART
endif

ifeq ($(TARGET),zynq)
  LSCRIPT_TEMPLATE:=AARCH64.ld
endif

ifeq ($(TARGET),pic32ck)
  APP_OBJS+=../hal/pic32c.o
endif

ifeq ($(TARGET), pic32cz)
  APP_OBJS+=../hal/pic32c.o
  ifeq ($(DEBUG_UART),1)
    APP_OBJS+=../hal/uart/uart_drv_pic32cz.o
  endif
endif

CFLAGS+=-I"$(WOLFBOOT_LIB_WOLFSSL)"

ifeq ($(TARGET),aurix_tc3xx)
  # Add BSP objects (same as in arch.mk for wolfBoot)
  APP_OBJS += $(TC3_DIR)/src/tc3_clock.o \
              $(TC3_DIR)/src/tc3_flash.o \
              $(TC3_DIR)/src/tc3_gpio.o \
              $(TC3_DIR)/src/tc3_uart.o \
              $(TC3_DIR)/src/tc3.o

  ifeq ($(AURIX_TC3_HSM),1)
    APP_OBJS += $(TC3_DIR)/src/tc3arm_crt.o \
                $(TC3_DIR)/src/tc3arm.o
	# Use TC3 Arm app linker script
    LSCRIPT_TEMPLATE = tc3arm_app.ld
  else
    APP_OBJS += $(TC3_DIR)/src/tc3tc_isr.o \
                $(TC3_DIR)/src/tc3tc_traps.o \
                $(TC3_DIR)/src/tc3tc.o \
                $(TC3_DIR)/src/tc3tc_crt.o
    # Use TC3 app linker script
    LSCRIPT_TEMPLATE = tc3tc_app.ld
  endif


  ifeq ($(WOLFHSM_SERVER),1)
    APP_OBJS += $(WOLFHSM_INFINEON_TC3XX)/port/server/port_halflash_df1.o
  endif

  # wolfHSM TC3xx port objects needed by the HAL (aurix_tc3xx.c)
  ifneq ($(filter 1,$(WOLFHSM_CLIENT) $(WOLFHSM_SERVER)),)
    APP_OBJS += $(WOLFHSM_INFINEON_TC3XX)/port/tchsm_common.o \
                $(WOLFHSM_INFINEON_TC3XX)/port/tchsm_hsmhost.o \
                $(WOLFBOOT_LIB_WOLFHSM)/src/wh_transport_mem.o
  endif

  ifeq ($(WOLFHSM_CLIENT),1)
    APP_OBJS += $(WOLFHSM_INFINEON_TC3XX)/port/client/hsm_ipc.o \
                $(WOLFHSM_INFINEON_TC3XX)/port/client/io.o \
                $(WOLFHSM_INFINEON_TC3XX)/port/client/tchsm_hh_host.o
  endif
endif

# On PPC64 (e5500/e6500) arch.mk turns on PPC32 SHA asm for the bootloader's
# image-verify link; strip it from the test-app's wolfCrypt so PPC_ASM alone
# controls the app's AES/SHA asm.
ifeq ($(PPC64),1)
  CFLAGS:=$(filter-out -DWOLFSSL_PPC32_ASM -DWOLFSSL_PPC32_ASM_INLINE,$(CFLAGS))
endif

## ARM Compiler for Embedded (USE_ARMCLANG=1): rebuild the link options from
## scratch, since the GNU-specific LDFLAGS accumulated above don't apply to
## armlink, and switch the linker script to a scatter file.
ifeq ($(USE_ARMCLANG),1)
  CFLAGS+=-D'_end_stack=Image$$$$ARM_LIB_STACK$$$$ZI$$$$Limit'
  CFLAGS+=-D'_start_heap=Image$$$$RW_RAM$$$$ZI$$$$Limit'
  # GCC-only flags accumulated above
  CFLAGS:=$(filter-out -Wstack-usage=% -gstabs,$(CFLAGS))
  LSCRIPT:=../config/target-app.sct
  LSCRIPT_TEMPLATE:=ARM-$(TARGET)-ns.sct
  LDFLAGS:=$(ARMCLANG_LDFLAGS) --map --list=image.map --scatter=$(LSCRIPT)
endif

# Capture final flags for locally built wolfSSL objects.
WOLFSSL_CFLAGS:=$(CFLAGS)
WOLFTPM_CFLAGS:=$(CFLAGS)
WOLFHSM_CFLAGS:=$(CFLAGS)

# Optional wolfIP network stack in the test-app.
#   ENABLE_WOLFIP=1       wolfIP ethernet port (nxp_fman, or nxp_enetc on
#                         LS1028A) + a link/PHY smoke test.
#   WOLFBOOT_TEST_TFTP=1  additionally pull in wolfIP core + TFTP client for
#                         the full network TFTP-fetch test.
# Point WOLFBOOT_LIB_WOLFIP at a wolfIP checkout, e.g.
#   make WOLFBOOT_LIB_WOLFIP=/path/to/wolfip ENABLE_WOLFIP=1 ...
ifeq ($(ENABLE_WOLFIP),1)
  # Fail early with a clear message if the wolfIP checkout is missing.
  ifeq ($(wildcard $(WOLFBOOT_LIB_WOLFIP)/src/wolfip.c),)
    $(error ENABLE_WOLFIP=1 but no wolfIP sources found at WOLFBOOT_LIB_WOLFIP=$(WOLFBOOT_LIB_WOLFIP). Set WOLFBOOT_LIB_WOLFIP to a wolfIP checkout, e.g. make WOLFBOOT_LIB_WOLFIP=/path/to/wolfip ENABLE_WOLFIP=1 ...)
  endif
  # Port by target: LS1028A (AArch64) uses ENETC; QorIQ PowerPC uses FMan.
  ifeq ($(TARGET),nxp_ls1028a)
    WOLFIP_PORT:=nxp_enetc
    WOLFIP_PORT_OBJ:=nxp_enetc.o
    CFLAGS+=-DWOLFIP_PORT_ENETC
  else
    WOLFIP_PORT:=nxp_fman
    WOLFIP_PORT_OBJ:=nxp_fman.o
    # The PPC test-app's _app_entry does no BSS-PLT fixup, so -mbss-plt
    # (arch.mk) would route cross-module libc calls (e.g. variable-size memcpy
    # in the wolfIP driver) through an uninitialized PLT stub branching to 0;
    # and default _FORTIFY_SOURCE rewrites memcpy/memmove into the _chk glibc
    # symbols (absent here -> R_PPC_JMP_SLOT imports, zero GOT slots). -fno-plt
    # + fortify-off keep those calls direct and unfortified. Scoped to the
    # wolfIP build so default builds are unchanged.
    CFLAGS+=-ffunction-sections -fdata-sections
    CFLAGS+=-fno-plt -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=0
  endif
  WOLFIP_PORTDIR:=$(WOLFBOOT_LIB_WOLFIP)/src/port/$(WOLFIP_PORT)
  CFLAGS+=-DENABLE_WOLFIP
  # wolfIP core (wolfip.c) provides the stack incl. DHCP/ICMP/TCP/UDP.
  WOLFIP_OBJS:=$(WOLFIP_PORTDIR)/$(WOLFIP_PORT_OBJ) \
               $(WOLFBOOT_LIB_WOLFIP)/src/wolfip.o
  ifeq ($(WOLFBOOT_TEST_TFTP),1)
    CFLAGS+=-DWOLFBOOT_TEST_TFTP
    WOLFIP_OBJS+=$(WOLFBOOT_LIB_WOLFIP)/src/tftp/wolftftp.o
  endif
  ifeq ($(WOLFIP_SPEED_TEST),1)
    CFLAGS+=-DWOLFIP_SPEED_TEST
  endif
  APP_OBJS+=$(WOLFIP_OBJS) wolfip_tftp_test.o
  # wolfIP TUs need the port headers first (so config.h resolves to the
  # port copy) and tolerate wolfIP's own style; drop -Werror/-Wstack-usage.
  WOLFIP_CFLAGS:=-I"$(WOLFIP_PORTDIR)" -I"$(WOLFBOOT_LIB_WOLFIP)" \
    $(filter-out -Werror -Wstack-usage=$(STACK_USAGE_LIMIT),$(CFLAGS)) \
    -DWOLFIP_ENABLE_TFTP=$(if $(filter 1,$(WOLFBOOT_TEST_TFTP)),1,0) \
    -Wno-unused -Wno-sign-compare -Wno-missing-field-initializers
endif

ifeq ($(WOLFHSM_CLIENT),1)
  CFLAGS += -DSTRING_USER -I"$(WOLFBOOT_LIB_WOLFSSL)"
  APP_OBJS += $(WOLFHSM_OBJS)
  APP_OBJS += $(sort $(patsubst $(WOLFBOOT_LIB_WOLFSSL)/%, $(WOLFBOOT_LIB_WOLFSSL)/%, $(WOLFCRYPT_OBJS)))
endif

ifeq ($(WOLFHSM_SERVER),1)
  CFLAGS += -DSTRING_USER -I"$(WOLFBOOT_LIB_WOLFSSL)"
  APP_OBJS += $(WOLFHSM_OBJS)
  APP_OBJS += $(sort $(patsubst $(WOLFBOOT_LIB_WOLFSSL)/%, $(WOLFBOOT_LIB_WOLFSSL)/%, $(WOLFCRYPT_OBJS)))
endif


standalone:CFLAGS+=-D"TEST_APP_STANDALONE"
standalone:LDFLAGS:=-T standalone.ld -Wl,-gc-sections -Wl,-Map=image.map

delta-extra-data:CFLAGS+=-D"TEST_DELTA_DATA=$(DELTA_DATA_SIZE)" -ffunction-sections -fdata-sections
delta-extra-data:LDFLAGS=-Wl,-Map=image.map

image.bin: image.elf
	@echo "\t[BIN] $@"
	$(Q)$(OBJCOPY) $(OBJCOPY_FLAGS) -O binary $^ $@

image.hex: image.elf
	@echo "\t[HEX] $@"
	$(Q)$(OBJCOPY) $(OBJCOPY_FLAGS) -O ihex $^ $@

image.srec: image.elf
	@echo "\t[SREC] $@"
	$(Q)$(OBJCOPY) $(OBJCOPY_FLAGS) -O srec $^ $@

APP_OBJS := $(patsubst $(WOLFBOOT_LIB_WOLFSSL)/%, \
    $(WOLFSSL_LOCAL_OBJDIR)/%, $(APP_OBJS))

APP_OBJS := $(patsubst $(WOLFBOOT_LIB_WOLFIP)/%, \
    $(WOLFIP_LOCAL_OBJDIR)/%, $(APP_OBJS))

ifeq ($(ELF_FLASH_SCATTER),1)
# When ELF_FLASH_SCATTER=1, preprocess the ELF file with the squashelf tool
SQUASHELF_TOOL = ../tools/squashelf/squashelf
image-orig.elf: $(APP_OBJS) $(LSCRIPT)
	@echo "\t[LD] $@"
	$(Q)$(LD) $(LDFLAGS) $(APP_OBJS) $(LIBS) $(OUTPUT_FLAG) $@

image.elf: image-orig.elf
	@echo "\t[SQUASHELF] $@"
	$(Q)$(SQUASHELF_TOOL) -v --nosht $< $@
else
# Default behavior when ELF_FLASH_SCATTER is not set
image.elf: $(APP_OBJS) $(LSCRIPT)
	@echo "\t[LD] $@"
	$(Q)$(LD) $(LDFLAGS) $(APP_OBJS) $(LIBS) $(OUTPUT_FLAG) $@
endif

standalone: image.bin

delta-extra-data: image.bin

../test-app/libwolfboot.o: ../src/libwolfboot.c FORCE
	@echo "\t[CC-$(ARCH)] $@"
	$(Q)$(CC) $(CFLAGS) -c $(OUTPUT_FLAG) $@ ../src/libwolfboot.c

../hal/$(TARGET).o: ../hal/$(TARGET).c FORCE
	$(Q)$(CC) $(CFLAGS) -c -o $(@) ../hal/$(TARGET).c

../hal/$(TARGET)_ns.o: ../hal/$(TARGET).c FORCE
	$(Q)$(CC) $(CFLAGS) -c -o $(@) ../hal/$(TARGET).c -DNONSECURE_APP

../hal/spi/spi_drv_$(SPI_TARGET)_ns.o: ../hal/spi/spi_drv_$(SPI_TARGET).c FORCE
	$(Q)$(CC) $(CFLAGS) -c -o $(@) ../hal/spi/spi_drv_$(SPI_TARGET).c -DNONSECURE_APP

../hal/uart/uart_drv_$(UART_TARGET)_ns.o: ../hal/uart/uart_drv_$(UART_TARGET).c FORCE
	$(Q)$(CC) $(CFLAGS) -c -o $(@) ../hal/uart/uart_drv_$(UART_TARGET).c -DNONSECURE_APP

board_$(BOARD).o: ../hal/boards/$(BOARD)/board.c
	@echo "\t[CC-$(ARCH)] $@"
	$(Q)$(CC) $(CFLAGS) -DDEBUG_UART -c $(OUTPUT_FLAG) $@ $<

%.o:%.c
	@echo "\t[CC-$(ARCH)] $@"
	$(Q)$(CC) $(CFLAGS) -c $(OUTPUT_FLAG) $@ $^

%.o:%.S
	@echo "\t[AS-$(ARCH)] $@"
	$(Q)$(CC) $(CFLAGS) -c $(OUTPUT_FLAG) $@ $^

$(WOLFSSL_LOCAL_OBJDIR)/%.o: %.c
	@echo "\t[CC-$(ARCH)] $@"
	$(Q)mkdir -p $(dir $@)
	$(Q)$(CC) $(WOLFSSL_CFLAGS) -c $(OUTPUT_FLAG) $@ $<

$(WOLFSSL_LOCAL_OBJDIR)/%.o: %.S
	@echo "\t[AS-$(ARCH)] $@"
	$(Q)mkdir -p $(dir $@)
	$(Q)$(CC) $(WOLFSSL_CFLAGS) -c $(OUTPUT_FLAG) $@ $<

$(WOLFTPM_LOCAL_OBJDIR)/%.o: %.c
	@echo "\t[CC-$(ARCH)] $@"
	$(Q)mkdir -p $(dir $@)
	$(Q)$(CC) $(WOLFTPM_CFLAGS) -c $(OUTPUT_FLAG) $@ $<

$(WOLFTPM_LOCAL_OBJDIR)/%.o: %.S
	@echo "\t[AS-$(ARCH)] $@"
	$(Q)mkdir -p $(dir $@)
	$(Q)$(CC) $(WOLFTPM_CFLAGS) -c $(OUTPUT_FLAG) $@ $<

$(WOLFHSM_LOCAL_OBJDIR)/%.o: %.c
	@echo "\t[CC-$(ARCH)] $@"
	$(Q)mkdir -p $(dir $@)
	$(Q)$(CC) $(WOLFHSM_CFLAGS) -c $(OUTPUT_FLAG) $@ $<

$(WOLFHSM_LOCAL_OBJDIR)/%.o: %.S
	@echo "\t[AS-$(ARCH)] $@"
	$(Q)mkdir -p $(dir $@)
	$(Q)$(CC) $(WOLFHSM_CFLAGS) -c $(OUTPUT_FLAG) $@ $<


$(WOLFIP_LOCAL_OBJDIR)/%.o: %.c
	@echo "\t[CC-$(ARCH)] $@"
	$(Q)mkdir -p $(dir $@)
	$(Q)$(CC) $(WOLFIP_CFLAGS) -c $(OUTPUT_FLAG) $@ $<

# Local test-app wolfIP glue, built with the wolfIP include/flag set.
wolfip_tftp_test.o: wolfip_tftp_test.c
	@echo "\t[CC-$(ARCH)] $@"
	$(Q)$(CC) $(WOLFIP_CFLAGS) -c $(OUTPUT_FLAG) $@ $<


clean:
	$(Q)rm -f *.bin *.elf tags *.o $(LSCRIPT) $(APP_OBJS) wcs/*.o
	$(Q)rm -rf $(WOLFSSL_LOCAL_OBJDIR) $(WOLFTPM_LOCAL_OBJDIR) \
		$(WOLFHSM_LOCAL_OBJDIR) $(WOLFIP_LOCAL_OBJDIR)

$(LSCRIPT): $(LSCRIPT_TEMPLATE) FORCE
	$(Q)printf "%d" $(WOLFBOOT_PARTITION_BOOT_ADDRESS) > .wolfboot-offset
	$(Q)printf "%d" $(WOLFBOOT_PARTITION_SIZE) > .partition-size
	$(Q)printf "%d" $(IMAGE_HEADER_SIZE) > .header-size
ifeq ($(ELF_FLASH_SCATTER),1)
# Optionally set the base address for the test-app linker MEMORY{} region if the
# HAL allows for it to be specified in the config via WOLFBOOT_ELF_EXEC_ADDRESS
ifdef WOLFBOOT_ELF_EXEC_ADDRESS
	# For ELF scatter mode, use execution space address directly (with no header offset)
	$(Q)printf "%d" $(WOLFBOOT_ELF_EXEC_ADDRESS) > .entry-point
	$(Q)printf "0x%X" `cat .entry-point` > .entry-point
	$(Q)printf "%d" $(WOLFBOOT_ELF_EXEC_SIZE) > .app-size
	$(Q)printf "0x%X" `cat .app-size` > .app-size
endif
else
	# Standard mode: boot partition address + header offset
	$(Q)expr `cat .wolfboot-offset` + `cat .header-size` > .entry-point
	$(Q)printf "0x%X" `cat .entry-point` > .entry-point
	$(Q)expr `cat .partition-size` - `cat .header-size` > .app-size
	$(Q)printf "0x%X" `cat .app-size` > .app-size
endif
	$(Q)cat $(LSCRIPT_TEMPLATE) | \
		sed -e "s/@WOLFBOOT_TEST_APP_SIZE@/`cat .app-size`/g" | \
		sed -e "s/@WOLFBOOT_TEST_APP_ADDRESS@/`cat .entry-point`/g" | \
		sed -e "s/@WOLFBOOT_LOAD_ADDRESS@/$(WOLFBOOT_LOAD_ADDRESS)/g" | \
		sed -e "s/@WOLFBOOT_PARTITION_BOOT_ADDRESS@/$(WOLFBOOT_PARTITION_BOOT_ADDRESS)/g" | \
		sed -e "s/@WOLFBOOT_PARTITION_SIZE@/$(WOLFBOOT_PARTITION_SIZE)/g" | \
		sed -e "s/@WOLFBOOT_PARTITION_UPDATE_ADDRESS@/$(WOLFBOOT_PARTITION_UPDATE_ADDRESS)/g" | \
		sed -e "s/@WOLFBOOT_PARTITION_SWAP_ADDRESS@/$(WOLFBOOT_PARTITION_SWAP_ADDRESS)/g" \
		> $(@)
	$(Q)rm -f .app-size .entry-point .wolfboot-offset .partition-size .header-size




FORCE:

.PHONY: FORCE clean
