Support for AURIX TC4xx host and CSRM cores

pull/890/head
Brett Nicholas 2026-08-26 16:47:09 -06:00
parent bafa907e9a
commit 6d652d444f
14 changed files with 1363 additions and 17 deletions

View File

@ -261,7 +261,14 @@ CFLAGS+=$(WOLFPSA_CFLAGS)
# Setup default optimizations (for GCC) # Setup default optimizations (for GCC)
ifeq ($(USE_GCC_HEADLESS),1) ifeq ($(USE_GCC_HEADLESS),1)
CFLAGS+=-Wall -Wextra -Wno-main -ffreestanding CFLAGS+=-Wall -Wextra -Wno-main -ffreestanding
CFLAGS+=-ffunction-sections -fdata-sections -fomit-frame-pointer ifneq (,$(filter aurix_tc4xx aurix_tc4xx_csrm,$(TARGET)))
# No -fdata-sections: tricore-elf-gcc 13 emits bare-named data sections
# (.varname, not .bss.varname) that escape the iLLD linker script's
# clear/copy tables, leaving statics uninitialized at boot.
CFLAGS+=-ffunction-sections -fomit-frame-pointer
else
CFLAGS+=-ffunction-sections -fdata-sections -fomit-frame-pointer
endif
# Allow unused parameters and functions # Allow unused parameters and functions
CFLAGS+=-Wno-unused-parameter -Wno-unused-function CFLAGS+=-Wno-unused-parameter -Wno-unused-function
# Error on unused variables # Error on unused variables
@ -587,31 +594,34 @@ endif
ifeq ($(WOLFHSM_SERVER),1) ifeq ($(WOLFHSM_SERVER),1)
_DO_WH_NVMTOOL:=1 _DO_WH_NVMTOOL:=1
endif endif
# Not every wolfHSM port provisions keys from a pre-built NVM image. A HAL may # Some wolfHSM ports do not provision keys from a pre-built NVM image.
# instead install the verification key into the server's key cache at boot (see # Their HAL installs the verification key into the server key cache at boot.
# hal_hsm_init_connect on pic32cz), which is the only option on targets whose # Set WOLFHSM_NVM_IMAGE=0 for those targets.
# server wipes its NVM partition on startup. Those set WOLFHSM_NVM_IMAGE=0.
WOLFHSM_NVM_IMAGE?=1 WOLFHSM_NVM_IMAGE?=1
ifeq ($(WOLFHSM_NVM_IMAGE),0) ifeq ($(WOLFHSM_NVM_IMAGE),0)
_DO_WH_NVMTOOL:= _DO_WH_NVMTOOL:=
endif endif
# Disable NVM image generation if user-provided keys without explicit USER_NVM_INIT # Disable NVM image generation for user-provided keys unless
# (providing USER_NVM_INIT allows users to supply keys and still generate a custom NVM image) # USER_NVM_INIT is set.
ifeq ($(_USER_PROVIDED_KEYS),1) ifeq ($(_USER_PROVIDED_KEYS),1)
ifeq ($(USER_NVM_INIT),) ifeq ($(USER_NVM_INIT),)
_DO_WH_NVMTOOL:= _DO_WH_NVMTOOL:=
endif endif
endif endif
ifeq ($(_DO_WH_NVMTOOL),1) ifeq ($(_DO_WH_NVMTOOL),1)
WH_NVM_TOOL_FLAGS ?= --invert-erased-byte
WH_NVM_HEX_ALIGN ?= 8
whnvmtool: whnvmtool:
@echo "Building wolfHSM NVM tool" @echo "Building wolfHSM NVM tool"
@$(MAKE) -C $(WOLFBOOT_LIB_WOLFHSM)/tools/whnvmtool @$(MAKE) -C $(WOLFBOOT_LIB_WOLFHSM)/tools/whnvmtool
nvm-image: $(PRIVATE_KEY) whnvmtool nvm-image: $(PRIVATE_KEY) whnvmtool
@echo "Generating wolfHSM NVM image" @echo "Generating wolfHSM NVM image"
$(Q)$(WOLFBOOT_LIB_WOLFHSM)/tools/whnvmtool/whnvmtool --image=$(WH_NVM_BIN) --size=$(WH_NVM_PART_SIZE) --invert-erased-byte $(NVM_CONFIG) $(Q)rm -f $(WH_NVM_BIN) $(WH_NVM_HEX)
@echo "Converting NVM image to Intel HEX format" $(Q)$(WOLFBOOT_LIB_WOLFHSM)/tools/whnvmtool/whnvmtool --image=$(WH_NVM_BIN) --size=$(WH_NVM_PART_SIZE) \
$(Q)$(OBJCOPY) -I binary -O ihex --change-address $(WH_NVM_BASE_ADDRESS) $(WH_NVM_BIN) $(WH_NVM_HEX) --hex=$(WH_NVM_HEX) --hex-base=$(WH_NVM_BASE_ADDRESS) --hex-align=$(WH_NVM_HEX_ALIGN) \
$(WH_NVM_TOOL_FLAGS) $(NVM_CONFIG)
@echo "NVM images generated: $(WH_NVM_BIN) and $(WH_NVM_HEX)" @echo "NVM images generated: $(WH_NVM_BIN) and $(WH_NVM_HEX)"
endif endif

203
arch.mk
View File

@ -2192,7 +2192,8 @@ endif
# #
# TARGET=aurix_tc3xx: AURIX TC3xx TriCore host # TARGET=aurix_tc3xx: AURIX TC3xx TriCore host
# TARGET=aurix_tc3xx_hsm: AURIX TC3xx Cortex-M3 HSM core # TARGET=aurix_tc3xx_hsm: AURIX TC3xx Cortex-M3 HSM core
# TARGET=aurix_tc4xx: AURIX TC4xx Tricore host (coming soon) # TARGET=aurix_tc4xx: AURIX TC4xx TriCore host
# TARGET=aurix_tc4xx_csrm: AURIX TC4xx CSRM (TriCore CPU6)
# Backwards compatibility migration error for legacy ARCH=AURIX_TC3 # Backwards compatibility migration error for legacy ARCH=AURIX_TC3
ifeq ($(filter clean keysclean,$(MAKECMDGOALS)),) ifeq ($(filter clean keysclean,$(MAKECMDGOALS)),)
@ -2387,13 +2388,203 @@ ifeq ($(ARCH), AURIX)
$(WOLFHSM_INFINEON_TC3XX)/port/client/tchsm_hh_host.o $(WOLFHSM_INFINEON_TC3XX)/port/client/tchsm_hh_host.o
endif endif
endif # aurix_tc3xx_hsm endif # !aurix_tc3xx_hsm
endif # TC3xx endif # TC3xx
# TC4xx specific ifneq (,$(filter aurix_tc4xx aurix_tc4xx_csrm,$(TARGET)))
ifeq ($(TARGET), aurix_tc4xx) # TC4xx
# Coming soon ;-) USE_GCC?=1
endif ARCH_FLASH_OFFSET?=0x80000000
# wolfHSM TC4xx port root. Expected that wolfBoot is inside as a submodule.
WOLFHSM_INFINEON_TC4XX?=$(abspath ..)
TC4_LLD_DIR?=$(WOLFHSM_INFINEON_TC4XX)/drivers
TC4_WB_DIR?=$(WOLFHSM_INFINEON_TC4XX)/port/wolfboot
# TC4 derivative device selection from the port device.mk.
include $(WOLFHSM_INFINEON_TC4XX)/device.mk
CROSS_COMPILE?=tricore-elf-
CFLAGS += -mcpu=$(DEV_MCPU) -D$(DEV_MACRO) $(DEV_XTAL_DEF) \
$(DEV_GCC13_CFLAGS)
CFLAGS += -Wall -fno-common -fstrict-volatile-bitfields \
-ffunction-sections -fno-builtin -std=gnu99 \
-DPART_BOOT_EXT -DPART_UPDATE_EXT -DPART_SWAP_EXT \
-DWOLFBOOT_LOADER_MAIN
# Vendor iLLD sources trip some -Wextra diagnostics
CFLAGS += -Wno-missing-field-initializers -Wno-unused-parameter \
-Wno-unused-variable -Wno-sign-compare -Wno-type-limits
# iLLD include paths. SSW configuration differs per core.
ifeq ($(TARGET), aurix_tc4xx_csrm)
CFLAGS += -I$(TC4_WB_DIR)/csrm -I$(TC4_WB_DIR)/csrm/Cfg_Ssw
else
CFLAGS += -I$(TC4_WB_DIR) -I$(TC4_WB_DIR)/Cfg_Ssw
endif
# Linker scripts ship with the port, not in hal/.
ifeq ($(TARGET), aurix_tc4xx_csrm)
LSCRIPT_IN=$(TC4_WB_DIR)/csrm/aurix_tc4xx_csrm.ld
else
LSCRIPT_IN=$(TC4_WB_DIR)/aurix_tc4xx.ld
endif
CFLAGS += \
-I$(TC4_LLD_DIR) \
-I$(TC4_LLD_DIR)/Infra/Ssw/TC4xx/Csrm \
-I$(TC4_LLD_DIR)/iLLD/TC4xx/Csrm \
-I$(TC4_LLD_DIR)/iLLD/TC4xx/Csrm/Cpu/Trap \
-I$(TC4_LLD_DIR)/Infra \
-I$(TC4_LLD_DIR)/Infra/Platform \
-I$(TC4_LLD_DIR)/Infra/Platform/Compilers \
-I$(TC4_LLD_DIR)/Infra/Sfr \
-I$(TC4_LLD_DIR)/Infra/Sfr/$(DEV_DERIV) \
-I$(TC4_LLD_DIR)/Infra/Ssw \
-I$(TC4_LLD_DIR)/Infra/Ssw/TC4xx \
-I$(TC4_LLD_DIR)/Infra/Ssw/TC4xx/Tricore \
-I$(TC4_LLD_DIR)/Service \
-I$(TC4_LLD_DIR)/Service/CpuGeneric \
-I$(TC4_LLD_DIR)/Service/CpuGeneric/If \
-I$(TC4_LLD_DIR)/Service/CpuGeneric/If/Ccu6If \
-I$(TC4_LLD_DIR)/Service/CpuGeneric/StdIf \
-I$(TC4_LLD_DIR)/Service/CpuGeneric/SysSe \
-I$(TC4_LLD_DIR)/Service/CpuGeneric/SysSe/Bsp \
-I$(TC4_LLD_DIR)/Service/CpuGeneric/SysSe/General \
-I$(TC4_LLD_DIR)/Service/CpuGeneric/SysSe/Time \
-I$(TC4_LLD_DIR)/Service/CpuGeneric/_Utilities \
-I$(TC4_LLD_DIR)/Service/Tricore \
-I$(TC4_LLD_DIR)/Service/Tricore/Comm \
-I$(TC4_LLD_DIR)/Service/Tricore/Math \
-I$(TC4_LLD_DIR)/iLLD \
-I$(TC4_LLD_DIR)/iLLD/TC4xx \
-I$(TC4_LLD_DIR)/iLLD/TC4xx/CpuGeneric \
-I$(TC4_LLD_DIR)/iLLD/TC4xx/CpuGeneric/Ap \
-I$(TC4_LLD_DIR)/iLLD/TC4xx/CpuGeneric/Ap/Std \
-I$(TC4_LLD_DIR)/iLLD/TC4xx/CpuGeneric/Asclin \
-I$(TC4_LLD_DIR)/iLLD/TC4xx/CpuGeneric/Asclin/Asc \
-I$(TC4_LLD_DIR)/iLLD/TC4xx/CpuGeneric/Asclin/Std \
-I$(TC4_LLD_DIR)/iLLD/TC4xx/CpuGeneric/Clock \
-I$(TC4_LLD_DIR)/iLLD/TC4xx/CpuGeneric/Clock/Std \
-I$(TC4_LLD_DIR)/iLLD/TC4xx/CpuGeneric/Egtm \
-I$(TC4_LLD_DIR)/iLLD/TC4xx/CpuGeneric/Egtm/Std \
-I$(TC4_LLD_DIR)/iLLD/TC4xx/CpuGeneric/Geth \
-I$(TC4_LLD_DIR)/iLLD/TC4xx/CpuGeneric/Geth/Std \
-I$(TC4_LLD_DIR)/iLLD/TC4xx/CpuGeneric/Port \
-I$(TC4_LLD_DIR)/iLLD/TC4xx/CpuGeneric/Port/Std \
-I$(TC4_LLD_DIR)/iLLD/TC4xx/CpuGeneric/Src \
-I$(TC4_LLD_DIR)/iLLD/TC4xx/CpuGeneric/Src/Std \
-I$(TC4_LLD_DIR)/iLLD/TC4xx/CpuGeneric/_Impl \
-I$(TC4_LLD_DIR)/iLLD/TC4xx/CpuGeneric/_Impl/$(DEV_DERIV) \
-I$(TC4_LLD_DIR)/iLLD/TC4xx/CpuGeneric/_Lib \
-I$(TC4_LLD_DIR)/iLLD/TC4xx/CpuGeneric/_Lib/DataHandling \
-I$(TC4_LLD_DIR)/iLLD/TC4xx/CpuGeneric/_Lib/Timer \
-I$(TC4_LLD_DIR)/iLLD/TC4xx/CpuGeneric/_PinMap \
-I$(TC4_LLD_DIR)/iLLD/TC4xx/CpuGeneric/_PinMap/$(DEV_DERIV) \
-I$(TC4_LLD_DIR)/iLLD/TC4xx/Tricore \
-I$(TC4_LLD_DIR)/iLLD/TC4xx/Tricore/Cpu \
-I$(TC4_LLD_DIR)/iLLD/TC4xx/Tricore/Cpu/Irq \
-I$(TC4_LLD_DIR)/iLLD/TC4xx/Tricore/Cpu/Std \
-I$(TC4_LLD_DIR)/iLLD/TC4xx/Tricore/Cpu/Trap \
-I$(TC4_LLD_DIR)/iLLD/TC4xx/Tricore/Flash/Std \
-I$(TC4_LLD_DIR)/iLLD/TC4xx/Tricore/Smu \
-I$(TC4_LLD_DIR)/iLLD/TC4xx/Tricore/Smu/Std \
-I$(TC4_LLD_DIR)/iLLD/TC4xx/Tricore/Stm \
-I$(TC4_LLD_DIR)/iLLD/TC4xx/Tricore/Stm/Std \
-I$(TC4_LLD_DIR)/iLLD/TC4xx/Tricore/Vmt \
-I$(TC4_LLD_DIR)/iLLD/TC4xx/Tricore/Vmt/Std \
-I$(TC4_LLD_DIR)/iLLD/TC4xx/Tricore/Wtu \
-I$(TC4_LLD_DIR)/iLLD/TC4xx/Tricore/Wtu/Std \
-I$(TC4_LLD_DIR)/iLLD/TC4xx/Tricore/_Impl \
-I$(TC4_LLD_DIR)/iLLD/TC4xx/Tricore/_Impl/$(DEV_DERIV)
# No TriCore asm in wolfCrypt
MATH_OBJS+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/sp_c32.o
# wolfHSM support
ifneq ($(filter 1,$(WOLFHSM_CLIENT) $(WOLFHSM_SERVER)),)
# Common wolfHSM port files.
CFLAGS += -I$(WOLFHSM_INFINEON_TC4XX)/port -DWOLFHSM_CFG_DMA \
-DWOLFHSM_CFG_NO_SYS_TIME
OBJS += $(WOLFHSM_INFINEON_TC4XX)/port/tchsm_hsmhost.o
OBJS += $(WOLFBOOT_LIB_WOLFHSM)/src/wh_transport_mem.o
# NVM image variables for the server key store.
WH_NVM_BIN ?= whNvmImage.bin
WH_NVM_HEX ?= whNvmImage.hex
WH_NVM_PART_SIZE ?= 0x8000
WH_NVM_BASE_ADDRESS ?= 0xAE800000
WH_NVM_TOOL_FLAGS ?=
WH_NVM_HEX_ALIGN ?= 8
NVM_CONFIG ?= tools/scripts/tc4xx/wolfBoot-wolfHSM-keys.nvminit
endif
ifeq ($(WOLFHSM_CLIENT),1)
# Client transport bring-up files.
CFLAGS += -I$(WOLFHSM_INFINEON_TC4XX)/port/client
OBJS += $(WOLFHSM_INFINEON_TC4XX)/port/client/tchsm_client.o \
$(WOLFHSM_INFINEON_TC4XX)/port/client/tchsm_hh_host.o \
$(WOLFHSM_INFINEON_TC4XX)/port/client/tchsm_spr_apu.o \
$(WOLFHSM_INFINEON_TC4XX)/port/client/tchsm_dma_client.o \
$(WOLFHSM_INFINEON_TC4XX)/port/client/tchsm_time.o
endif
ifeq ($(TARGET), aurix_tc4xx_csrm)
CFLAGS += -msoft-sp-float -msoft-dp-float
LDFLAGS += -msoft-sp-float -msoft-dp-float
# Full-system CSRM wolfBoot target leaves host release to tchsm-server.
ifeq ($(AURIX_TC4_FULLSYS),1)
CFLAGS += -DWOLFBOOT_AURIX_TC4XX_FULLSYS
LSCRIPT_IN=$(TC4_WB_DIR)/csrm/aurix_tc4xx_csrm_fullsys.ld
endif
endif
LDFLAGS += -mcpu=$(DEV_MCPU) -Wl,--cref -Wl,-Map="wolfboot.map"
# Remove UCB, BMHD, and other empty but loadable elf sections from wolfBoot.bin
# such that the binary image can be contiguous
OBJCOPY_FLAGS+=-R '.bmhd*' -R '.usercfg*' -R '.csusercfg*' -R '.sdata4' -R '.sdata' -R '.zdata'
# iLLD startup software and drivers used by the HAL.
TC4_LLD_SRCS := \
$(wildcard $(TC4_LLD_DIR)/Infra/Platform/Compilers/*.c) \
$(TC4_LLD_DIR)/Infra/Ssw/TC4xx/Tricore/Ifx_Ssw_Infra.c \
$(wildcard $(TC4_LLD_DIR)/iLLD/TC4xx/CpuGeneric/Ap/Std/*.c) \
$(wildcard $(TC4_LLD_DIR)/iLLD/TC4xx/CpuGeneric/Asclin/Std/*.c) \
$(wildcard $(TC4_LLD_DIR)/iLLD/TC4xx/CpuGeneric/Clock/Std/*.c) \
$(wildcard $(TC4_LLD_DIR)/iLLD/TC4xx/CpuGeneric/Port/Std/*.c) \
$(wildcard $(TC4_LLD_DIR)/iLLD/TC4xx/CpuGeneric/Src/Std/*.c) \
$(wildcard $(TC4_LLD_DIR)/iLLD/TC4xx/CpuGeneric/_Impl/*.c) \
$(wildcard $(TC4_LLD_DIR)/iLLD/TC4xx/CpuGeneric/_Impl/$(DEV_DERIV)/*.c) \
$(wildcard $(TC4_LLD_DIR)/iLLD/TC4xx/CpuGeneric/_PinMap/IfxAsclin_PinMap*.c) \
$(wildcard $(TC4_LLD_DIR)/iLLD/TC4xx/CpuGeneric/_PinMap/$(DEV_DERIV)/IfxAsclin_PinMap*.c) \
$(wildcard $(TC4_LLD_DIR)/iLLD/TC4xx/Tricore/Cpu/Std/*.c) \
$(wildcard $(TC4_LLD_DIR)/iLLD/TC4xx/Tricore/Stm/Std/*.c) \
$(wildcard $(TC4_LLD_DIR)/iLLD/TC4xx/Tricore/Wtu/Std/*.c) \
$(wildcard $(TC4_LLD_DIR)/iLLD/TC4xx/Tricore/_Impl/*.c)
ifeq ($(TARGET), aurix_tc4xx_csrm)
# CSRM (CPU6) startup software + trap table
TC4_LLD_SRCS += \
$(TC4_LLD_DIR)/Infra/Ssw/TC4xx/Csrm/Ifx_Ssw_Tc6.c \
$(TC4_LLD_DIR)/iLLD/TC4xx/Csrm/Cpu/Trap/IfxCpu_Trap_Cs.c
OBJS += $(TC4_LLD_SRCS:.c=.o)
OBJS += $(TC4_WB_DIR)/csrm/Cfg_Ssw/Ifx_Cfg_Ssw.o \
$(TC4_WB_DIR)/csrm/Cfg_Ssw/Ifx_Cfg_SswBmhdCs.o \
$(TC4_WB_DIR)/csrm/tc4_wolfboot_csrm_main.o
else
# Host CPU0 startup software and trap table.
TC4_LLD_SRCS += \
$(TC4_LLD_DIR)/Infra/Ssw/TC4xx/Tricore/Ifx_Ssw_Tc0.c \
$(wildcard $(TC4_LLD_DIR)/iLLD/TC4xx/Tricore/Cpu/Irq/*.c) \
$(wildcard $(TC4_LLD_DIR)/iLLD/TC4xx/Tricore/Cpu/Trap/*.c) \
$(wildcard $(TC4_LLD_DIR)/iLLD/TC4xx/Tricore/Smu/Std/*.c) \
$(wildcard $(TC4_LLD_DIR)/iLLD/TC4xx/Tricore/Vmt/Std/*.c)
OBJS += $(TC4_LLD_SRCS:.c=.o)
OBJS += $(TC4_WB_DIR)/Cfg_Ssw/Ifx_Cfg_Ssw.o \
$(TC4_WB_DIR)/Cfg_Ssw/Ifx_Cfg_SswBmhd.o \
$(TC4_WB_DIR)/tc4_wolfboot_main.o
endif
endif # TC4xx
endif endif
CFLAGS+=-DARCH_FLASH_OFFSET=$(ARCH_FLASH_OFFSET) CFLAGS+=-DARCH_FLASH_OFFSET=$(ARCH_FLASH_OFFSET)

View File

@ -0,0 +1,26 @@
ARCH?=AURIX
TARGET?=aurix_tc4xx_csrm
SIGN?=ECC256
HASH?=SHA256
DEBUG?=0
NO_ASM?=1
WOLFBOOT_VERSION?=1
V?=0
SPMATH?=1
RAM_CODE?=1
EXT_FLASH?=1
EXT_BOOT=1
EXT_UPDATE=1
EXT_SWAP=1
FLAGS_INVERT=1
FLASH_MULTI_SECTOR_ERASE=1
DEBUG_UART=1
PRINTF_ENABLED=1
WOLFBOOT_IMG_HASH_ONESHOT=1
ARCH_FLASH_OFFSET=0x84000000
WOLFBOOT_SECTOR_SIZE=0x4000
WOLFBOOT_PARTITION_SIZE=0x70000
WOLFBOOT_PARTITION_BOOT_ADDRESS=0x84018000
WOLFBOOT_PARTITION_UPDATE_ADDRESS=0x84088000
WOLFBOOT_PARTITION_SWAP_ADDRESS=0x840F8000

View File

@ -0,0 +1,26 @@
ARCH?=AURIX
TARGET?=aurix_tc4xx
SIGN?=ECC256
HASH?=SHA256
DEBUG?=0
NO_ASM?=1
WOLFBOOT_VERSION?=1
V?=0
SPMATH?=1
RAM_CODE?=1
EXT_FLASH?=1
EXT_BOOT=1
EXT_UPDATE=1
EXT_SWAP=1
FLAGS_INVERT=1
FLASH_MULTI_SECTOR_ERASE=1
DEBUG_UART=1
PRINTF_ENABLED=1
WOLFBOOT_IMG_HASH_ONESHOT=1
ARCH_FLASH_OFFSET=0x80000000
WOLFBOOT_SECTOR_SIZE=0x4000
WOLFBOOT_PARTITION_SIZE=0x180000
WOLFBOOT_PARTITION_BOOT_ADDRESS=0x80400000
WOLFBOOT_PARTITION_UPDATE_ADDRESS=0x80580000
WOLFBOOT_PARTITION_SWAP_ADDRESS=0x80700000

View File

@ -0,0 +1,30 @@
ARCH?=AURIX
TARGET?=aurix_tc4xx_csrm
AURIX_TC4_FULLSYS=1
SIGN?=ECC256
HASH?=SHA256
DEBUG?=0
NO_ASM?=1
WOLFBOOT_VERSION?=1
V?=0
SPMATH?=1
RAM_CODE?=1
EXT_FLASH?=1
EXT_BOOT=1
EXT_UPDATE=1
EXT_SWAP=1
FLAGS_INVERT=1
FLASH_MULTI_SECTOR_ERASE=1
DEBUG_UART=1
PRINTF_ENABLED=1
WOLFBOOT_IMG_HASH_ONESHOT=1
# Full-system CSRM layout.
# Reserve 64 KiB for wolfBoot.
# Use 0x74000 BOOT and UPDATE partitions for the signed server.
ARCH_FLASH_OFFSET=0x84000000
WOLFBOOT_SECTOR_SIZE=0x4000
WOLFBOOT_PARTITION_SIZE=0x74000
WOLFBOOT_PARTITION_BOOT_ADDRESS=0x84010000
WOLFBOOT_PARTITION_UPDATE_ADDRESS=0x84084000
WOLFBOOT_PARTITION_SWAP_ADDRESS=0x840F8000

View File

@ -0,0 +1,37 @@
ARCH?=AURIX
TARGET?=aurix_tc4xx
SIGN?=ECC256
HASH?=SHA256
DEBUG?=0
NO_ASM?=1
WOLFBOOT_VERSION?=1
V?=0
SPMATH?=1
RAM_CODE?=1
EXT_FLASH?=1
EXT_BOOT=1
EXT_UPDATE=1
EXT_SWAP=1
FLAGS_INVERT=1
FLASH_MULTI_SECTOR_ERASE=1
DEBUG_UART=1
PRINTF_ENABLED=1
WOLFBOOT_IMG_HASH_ONESHOT=1
# wolfHSM client mode for the full-system chain.
# Hash and ECC verify are offloaded to tchsm-server.
# Align COMM_DATA_LEN with the server build.
WOLFHSM_CLIENT=1
WOLFHSM_CFG_COMM_DATA_LEN=8192
# Detached self header for server cross-verify.
WOLFBOOT_SELF_HEADER=1
SELF_HEADER_EXT=1
WOLFBOOT_PARTITION_SELF_HEADER_ADDRESS=0x80100000
ARCH_FLASH_OFFSET=0x80000000
WOLFBOOT_SECTOR_SIZE=0x4000
WOLFBOOT_PARTITION_SIZE=0x180000
WOLFBOOT_PARTITION_BOOT_ADDRESS=0x80400000
WOLFBOOT_PARTITION_UPDATE_ADDRESS=0x80580000
WOLFBOOT_PARTITION_SWAP_ADDRESS=0x80700000

View File

@ -10,6 +10,7 @@ This README describes configuration of supported targets.
* [Cortex-A72 / Raspberry Pi Compute Module 4](#cortex-a72--raspberry-pi-compute-module-4-bcm2711) * [Cortex-A72 / Raspberry Pi Compute Module 4](#cortex-a72--raspberry-pi-compute-module-4-bcm2711)
* [Cypress PSoC-6](#cypress-psoc-6) * [Cypress PSoC-6](#cypress-psoc-6)
* [Infineon AURIX TC3xx](#infineon-aurix-tc3xx) * [Infineon AURIX TC3xx](#infineon-aurix-tc3xx)
* [Infineon AURIX TC4xx](#infineon-aurix-tc4xx)
* [Intel x86-64 Intel FSP](#intel-x86_64-with-intel-fsp-support) * [Intel x86-64 Intel FSP](#intel-x86_64-with-intel-fsp-support)
* [Kontron VX3060-S2](#kontron-vx3060-s2) * [Kontron VX3060-S2](#kontron-vx3060-s2)
* [Microchip PIC32CK](#microchip-pic32ck) * [Microchip PIC32CK](#microchip-pic32ck)
@ -8681,6 +8682,17 @@ Currently, wolfBoot for TC3xx is distributed as part of the wolfHSM TC3xx platfo
For access to the TC3xx platform release or for more information on using wolfBoot and wolfHSM on AURIX devices, contact [facts@wolfssl.com](mailto:facts@wolfssl.com). For access to the TC3xx platform release or for more information on using wolfBoot and wolfHSM on AURIX devices, contact [facts@wolfssl.com](mailto:facts@wolfssl.com).
## Infineon AURIX TC4xx
wolfBoot supports the Infineon AURIX TC4xx family and includes a demo application for the TC4D7 AURIX LiteKit-V2.1. It can be configured to run on either the TriCore application cores or the CSRM core.
Both cores build with `ARCH=AURIX`. `TARGET` selects the core: `aurix_tc4xx` for the TriCore application cores and `aurix_tc4xx_csrm` for the CSRM core. Example configurations are in `config/examples/aurix-tc4xx-*.config`.
On AURIX TC4xx devices, wolfBoot can also integrate with [wolfHSM](https://www.wolfssl.com/products/wolfhsm/) to offload cryptographic operations and key management to the CSRM core.
Currently, wolfBoot for TC4xx is distributed as part of the wolfHSM TC4xx platform release bundle, not as a standalone package. This bundle is under NDA and is not publicly available.
For access to the TC4xx platform release or for more information on using wolfBoot and wolfHSM on AURIX devices, contact [facts@wolfssl.com](mailto:facts@wolfssl.com).
## Vorago VA416x0 ## Vorago VA416x0

793
hal/aurix_tc4xx.c 100644
View File

@ -0,0 +1,793 @@
/* aurix_tc4xx.c
*
* Copyright (C) 2014-2026 wolfSSL Inc.
*
* This file is part of wolfBoot.
*
* wolfBoot is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* wolfBoot is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with wolfBoot. If not, see <http://www.gnu.org/licenses/>.
*/
/* wolfBoot HAL for the Infineon AURIX TC4xx host and CSRM cores.
*/
#include <stdint.h>
#include <string.h>
/* wolfBoot headers */
#include "hal.h"
#include "image.h" /* for RAMFUNCTION */
#include "loader.h" /* for wolfBoot_panic */
#include "printf.h"
/* iLLD headers */
#include "Ifx_Types.h"
#include "IfxAsclin.h"
#include "IfxAsclin_PinMap.h"
#include "IfxCpu.h"
#include "IfxWtu.h"
#ifndef TARGET_aurix_tc4xx_csrm
#include "IfxClock.h"
#endif
#if defined(WOLFBOOT_ENABLE_WOLFHSM_CLIENT)
#include "IfxApApu.h"
#include "IfxApProt.h"
#include "IfxSrc.h"
/* wolfHSM headers */
#include "wolfhsm/wh_client.h"
#include "wolfhsm/wh_error.h"
/* wolfHSM AURIX TC4xx port headers */
#include "tchsm_hsmhost.h"
#include "tchsm_client.h"
#include "tchsm_spr_apu.h"
/* wolfHSM client ID for the HSM server.
* Align with whnvmtool provisioning. */
#ifndef WOLFBOOT_WOLFHSM_CLIENT_ID
#error \
"WOLFBOOT_WOLFHSM_CLIENT_ID is not defined. Set WOLFHSM_CLIENT_ID in your .config or on the make command line."
#endif
/* HAL symbols exported for wolfBoot wolfHSM client mode. */
whClientContext hsmClientCtx = {0};
/* The server hashes host flash by address. */
const int hsmDevIdHash = WH_DEV_ID_DMA;
const int hsmDevIdPubKey = WH_DEV_ID;
/* Verify public key stored in wolfHSM NVM. */
const int hsmKeyIdPubKey = 0xFF;
#ifdef EXT_ENCRYPT
#error "AURIX TC4xx does not support firmware encryption with wolfHSM (yet)"
#endif
_Static_assert(WOLFBOOT_WOLFHSM_CLIENT_ID == TCHSM_HSMHOST_CLIENT_APP0,
"WOLFHSM_CLIENT_ID must match the port's APP0 client ID");
#endif /* WOLFBOOT_ENABLE_WOLFHSM_CLIENT */
#define TC4_PFLASH_PAGE_SIZE (32u)
#define TC4_PFLASH_BURST_SIZE (512u)
#ifdef TARGET_aurix_tc4xx_csrm
#define TC4_PROG_CHUNK_SIZE TC4_PFLASH_PAGE_SIZE
#else
#define TC4_PROG_CHUNK_SIZE TC4_PFLASH_BURST_SIZE
#endif
/* Convert between the cached (0x8...) segment used by the wolfBoot
* partition configuration and the non-cached (0xA...) alias the command
* interface requires. */
#define TC4_FLASH_NC(addr) (((uint32_t)(addr)) | 0x20000000u)
/* Select FCI based on CPU */
#ifdef TARGET_aurix_tc4xx_csrm
#define TC4_CMD_BASE (0xF80C0000u)
#else
#define TC4_CMD_BASE (0xF8080000u)
#endif
#define TC4_CMD_REG(off) ((volatile uint32_t*)(TC4_CMD_BASE | (off)))
#define TC4_CMD_MODE TC4_CMD_REG(0x5554u) /* mode/status cycles */
#define TC4_CMD_LOAD2X32 TC4_CMD_REG(0x55F4u) /* page assembly, 2x32-bit */
#define TC4_CMD_ADDR TC4_CMD_REG(0xAA50u) /* command word 1: address */
#define TC4_CMD_COUNT TC4_CMD_REG(0xAA58u) /* command word 2: count */
#define TC4_CMD_CODE TC4_CMD_REG(0xAAA8u) /* command code, written twice */
#define TC4_MODE_CLEAR_STATUS (0xFAu)
#define TC4_MODE_PF_PAGEMODE (0x50u)
#define TC4_MODE_RESET_READ (0xF0u)
/* DMU command interface status/error registers (CSCI mirrors HCI at +0x80) */
#define TC4_DMU_REG(addr) ((volatile uint32_t*)(addr))
#ifdef TARGET_aurix_tc4xx_csrm
#define TC4_HCI_STATUS TC4_DMU_REG(0xF8040084u)
#define TC4_HCI_ERR TC4_DMU_REG(0xF8040090u)
#define TC4_HCI_CLRERR TC4_DMU_REG(0xF8040094u)
#else
#define TC4_HCI_STATUS TC4_DMU_REG(0xF8040004u)
#define TC4_HCI_ERR TC4_DMU_REG(0xF8040010u)
#define TC4_HCI_CLRERR TC4_DMU_REG(0xF8040014u)
#endif
#define TC4_GP_BKALLOC TC4_DMU_REG(0xF8040A00u)
#define TC4_BKALLOC_CSRMPF (1u << 18)
/* HCI.STATUS fields */
#define TC4_STATUS_BANKS_BUSY (0x000F0FFFu) /* per-bank busy + host DF + FSI \
*/
#define TC4_STATUS_PFPAGE (1u << 25)
#define TC4_STATUS_REQDONE (1u << 31)
#define TC4_ERR_OPFAIL_MASK \
(0x00010077u) /* ADER|SQER|PROER|ABER|CLER|PVER|OPER */
#define TC4_ERR_EVER (1u << 7)
#define TC4_CLRERR_ALL (0xF7u) /* OPER (bit16) has no clear bit */
/* Bounded wait limits for flash commands */
#define TC4_BUSY_SPIN_LIMIT (50000000u)
#define TC4_REQDONE_SPIN_LIMIT (1000000u)
#define WOLFBOOT_AURIX_RESET_REASON (0x5742) /* "WB" */
/* Helper macros for the base address of the page or sector containing addr */
#define GET_PAGE_ADDR(addr) ((uintptr_t)(addr) & ~(TC4_PFLASH_PAGE_SIZE - 1))
#define GET_SECTOR_ADDR(addr) ((uintptr_t)(addr) & ~(WOLFBOOT_SECTOR_SIZE - 1))
#define TC4_DSYNC() __asm volatile("dsync" ::: "memory")
/* RAM buffer holding one flash sector for read-modify-write operations */
static uint32_t sectorBuffer[WOLFBOOT_SECTOR_SIZE / sizeof(uint32_t)];
static void RAMFUNCTION flashClearStatus(void)
{
*TC4_CMD_MODE = TC4_MODE_CLEAR_STATUS;
TC4_DSYNC();
}
/* Wait for all host banks idle and for REQDONE (end of sequence status).
* A timeout fails the operation.
* Returns 0 on completion, -1 on timeout. */
static int RAMFUNCTION flashWaitDone(void)
{
uint32_t spins;
spins = TC4_BUSY_SPIN_LIMIT;
while (((*TC4_HCI_STATUS & TC4_STATUS_BANKS_BUSY) != 0u) &&
(--spins != 0u)) {
}
if (spins == 0u) {
return -1;
}
spins = TC4_REQDONE_SPIN_LIMIT;
while (((*TC4_HCI_STATUS & TC4_STATUS_REQDONE) == 0u) && (--spins != 0u)) {
}
if (spins == 0u) {
return -1;
}
TC4_DSYNC();
return 0;
}
/* Read and clear the error flags. Returns the raw error register value. */
static uint32_t RAMFUNCTION flashGetClearErrors(void)
{
uint32_t err = *TC4_HCI_ERR;
*TC4_HCI_CLRERR = TC4_CLRERR_ALL;
TC4_DSYNC();
return err;
}
/* Issue a flash command and wait for completion. Returns the error flags on
* completion or TC4_ERR_OPFAIL_MASK on timeout. */
static uint32_t RAMFUNCTION flashCommand(uint32_t address, uint32_t count,
uint32_t code1, uint32_t code2)
{
flashClearStatus();
*TC4_CMD_ADDR = TC4_FLASH_NC(address);
*TC4_CMD_COUNT = count;
*TC4_CMD_CODE = code1;
*TC4_CMD_CODE = code2;
TC4_DSYNC();
if (flashWaitDone() != 0) {
return TC4_ERR_OPFAIL_MASK;
}
return flashGetClearErrors();
}
/* Blank check one page via the hardware erase-verify command.
* Returns 1 if erased, 0 if programmed, -1 on error. */
static int RAMFUNCTION flashIsPageErased(uint32_t pageAddr)
{
uint32_t err = flashCommand(pageAddr, 0u, 0x80u, 0x56u);
if ((err & TC4_ERR_OPFAIL_MASK) != 0u) {
return -1;
}
return ((err & TC4_ERR_EVER) != 0u) ? 0 : 1;
}
/* Erase one 16KB logical sector. Sectors are erased one at a time due to issues
* with multi-sector erases leaving the busy flag set. Returns 0 on success. */
static int RAMFUNCTION flashEraseSector(uint32_t sectorAddr)
{
uint32_t err = flashCommand(sectorAddr, 1u, 0x80u, 0x50u);
if ((err & TC4_ERR_OPFAIL_MASK) != 0u) {
return -1;
}
return 0;
}
/* Program a naturally aligned group of pages (one page or one burst) that
* is already erased. data must hold size bytes; size is either
* TC4_PFLASH_PAGE_SIZE or TC4_PFLASH_BURST_SIZE. Returns 0 on success. */
static int RAMFUNCTION flashProgramAligned(uint32_t addr, const uint32_t* data,
uint32_t size)
{
uint32_t i;
uint32_t err;
uint32_t spins;
/* Enter page mode and wait for the assembly buffer to be ready */
flashClearStatus();
*TC4_CMD_MODE = TC4_MODE_PF_PAGEMODE;
TC4_DSYNC();
spins = TC4_REQDONE_SPIN_LIMIT;
while (((*TC4_HCI_STATUS & TC4_STATUS_PFPAGE) == 0u) && (--spins != 0u)) {
}
if (spins == 0u) {
return -1;
}
/* Fill the page assembly buffer, two 32-bit words per cycle */
for (i = 0; i < (size / sizeof(uint32_t)); i += 2u) {
*TC4_CMD_LOAD2X32 = data[i];
*TC4_CMD_LOAD2X32 = data[i + 1u];
}
TC4_DSYNC();
/* Write Page (0xAA) or Write Burst (0xA6) */
err = flashCommand(addr, 0u, 0xA0u,
(size == TC4_PFLASH_BURST_SIZE) ? 0xA6u : 0xAAu);
if ((err & TC4_ERR_OPFAIL_MASK) != 0u) {
/* Leave page mode so the interface is not stuck */
*TC4_CMD_MODE = TC4_MODE_RESET_READ;
TC4_DSYNC();
return -1;
}
return 0;
}
/* Read len bytes at address, which must not span an erased page (callers
* blank-check first). Reads go through the non-cached alias so no stale
* cache lines are involved. */
static void RAMFUNCTION flashRead(uint32_t address, uint8_t* data, uint32_t len)
{
const volatile uint8_t* src =
(const volatile uint8_t*)TC4_FLASH_NC(address);
uint32_t i;
for (i = 0; i < len; i++) {
data[i] = src[i];
}
}
/* Read an entire sector into sectorBuffer, substituting the erased-byte
* value for erased pages so no erased cell is ever read. */
static void RAMFUNCTION cacheSector(uint32_t sectorAddress)
{
uint32_t page;
for (page = 0; page < WOLFBOOT_SECTOR_SIZE; page += TC4_PFLASH_PAGE_SIZE) {
uint32_t* dst = sectorBuffer + (page / sizeof(uint32_t));
int erased = flashIsPageErased(sectorAddress + page);
if (erased < 0) {
wolfBoot_panic();
}
else if (erased == 1) {
uint32_t i;
for (i = 0; i < TC4_PFLASH_PAGE_SIZE / sizeof(uint32_t); i++) {
dst[i] = FLASH_WORD_ERASED;
}
}
else {
flashRead(sectorAddress + page, (uint8_t*)dst,
TC4_PFLASH_PAGE_SIZE);
}
}
}
/* Program sectorBuffer back into an erased sector, chunk by chunk
* (bursts on the host interface, single pages on the CSRM) */
static void RAMFUNCTION programCachedSector(uint32_t sectorAddress)
{
uint32_t off;
for (off = 0; off < WOLFBOOT_SECTOR_SIZE; off += TC4_PROG_CHUNK_SIZE) {
if (flashProgramAligned(sectorAddress + off,
sectorBuffer + (off / sizeof(uint32_t)),
TC4_PROG_CHUNK_SIZE) != 0) {
wolfBoot_panic();
}
}
}
/* Program unaligned data into erased flash, page by page */
static int RAMFUNCTION programBytesToErasedFlash(uint32_t address,
const uint8_t* data, int size)
{
uint32_t pageBuffer[TC4_PFLASH_PAGE_SIZE / sizeof(uint32_t)];
uint32_t pageAddress = GET_PAGE_ADDR(address);
uint32_t offset = address % TC4_PFLASH_PAGE_SIZE;
while (size > 0) {
uint32_t toWrite = TC4_PFLASH_PAGE_SIZE - offset;
uint32_t i;
if (toWrite > (uint32_t)size) {
toWrite = (uint32_t)size;
}
for (i = 0; i < TC4_PFLASH_PAGE_SIZE / sizeof(uint32_t); i++) {
pageBuffer[i] = FLASH_WORD_ERASED;
}
memcpy((uint8_t*)pageBuffer + offset, data, toWrite);
if (flashProgramAligned(pageAddress, pageBuffer,
TC4_PFLASH_PAGE_SIZE) != 0) {
return -1;
}
size -= toWrite;
data += toWrite;
address += toWrite;
pageAddress = GET_PAGE_ADDR(address);
offset = address % TC4_PFLASH_PAGE_SIZE;
}
return 0;
}
#if defined(DEBUG_UART) || defined(UART_FLASH)
#define TC4_UART (&MODULE_ASCLIN0)
#define TC4_UART_BAUD (115200u)
#define TC4_UART_FIFO_SIZE (16u)
int uart_tx(const uint8_t c);
int uart_rx(uint8_t* c);
void uart_init(void);
void uart_write(const char* buf, unsigned int sz);
void uart_init(void)
{
Ifx_ASCLIN* u = TC4_UART;
IfxAsclin_enableModule(u);
IfxAsclin_setClockSource(u, IfxAsclin_ClockSource_noClock);
IfxAsclin_setFrameMode(u, IfxAsclin_FrameMode_initialise);
IfxAsclin_setPrescaler(u, 1);
IfxAsclin_setClockSource(u, IfxAsclin_ClockSource_ascFastClock);
(void)IfxAsclin_setBitTiming(
u, (float32)TC4_UART_BAUD, IfxAsclin_OversamplingFactor_16,
IfxAsclin_SamplePointPosition_8, IfxAsclin_SamplesPerBit_three);
IfxAsclin_setClockSource(u, IfxAsclin_ClockSource_noClock);
IfxAsclin_enableParity(u, FALSE);
IfxAsclin_setStopBit(u, IfxAsclin_StopBit_1);
IfxAsclin_setShiftDirection(u, IfxAsclin_ShiftDirection_lsbFirst);
IfxAsclin_setDataLength(u, IfxAsclin_DataLength_8);
IfxAsclin_setTxFifoInletWidth(u, IfxAsclin_TxFifoInletWidth_1);
IfxAsclin_setRxFifoOutletWidth(u, IfxAsclin_RxFifoOutletWidth_1);
IfxAsclin_setFrameMode(u, IfxAsclin_FrameMode_asc);
IfxAsclin_initTxPin(&IfxAsclin0_TX_F_P14_0_OUT, IfxPort_OutputMode_pushPull,
IfxPort_PadDriver_cmosAutomotiveSpeed1);
IfxAsclin_initRxPin(&IfxAsclin0_RXA_F_P14_1_IN, IfxPort_InputMode_pullUp,
IfxPort_PadDriver_cmosAutomotiveSpeed1);
IfxAsclin_setClockSource(u, IfxAsclin_ClockSource_ascFastClock);
IfxAsclin_disableAllFlags(u);
IfxAsclin_clearAllFlags(u);
IfxAsclin_flushTxFifo(u);
IfxAsclin_enableTxFifoOutlet(u, TRUE);
}
int uart_tx(const uint8_t c)
{
Ifx_ASCLIN* u = TC4_UART;
while (IfxAsclin_getTxFifoFillLevel(u) >= TC4_UART_FIFO_SIZE) {
}
IfxAsclin_writeTxData(u, c);
return 1;
}
int uart_rx(uint8_t* c)
{
(void)c;
return 0;
}
void uart_write(const char* buf, unsigned int sz)
{
while (sz > 0) {
if (*buf == '\n') {
(void)uart_tx('\r');
}
(void)uart_tx(*buf++);
sz--;
}
}
/* Block until the TX FIFO has fully drained onto the wire */
static void uart_flush(void)
{
Ifx_ASCLIN* u = TC4_UART;
volatile uint32_t i;
while (IfxAsclin_getTxFifoFillLevel(u) != 0u) {
}
/* Delay in case TC flag is still set from an earlier idle
* period while the last frame sits in the shift reg. */
for (i = 0; i < 200000u; i++) {
}
}
#endif /* DEBUG_UART || UART_FLASH */
/*
* wolfBoot HAL entry points
*/
void hal_init(void)
{
#ifdef TARGET_aurix_tc4xx_csrm
IfxWtu_disableSecurityWatchdog(IfxWtu_getSecurityWatchdogPassword());
/* The CSRM PFLASH bank must be allocated to the CSRM or the CSCI
* command writes will fail silently */
if ((*TC4_GP_BKALLOC & TC4_BKALLOC_CSRMPF) == 0u) {
wolfBoot_panic();
}
#else
IfxWtu_disableCpuWatchdog(IfxWtu_getCpuWatchdogPassword());
IfxWtu_disableSystemWatchdog(IfxWtu_getSystemWatchdogPassword());
/* Refuse to run if a host PFLASH bank has been reallocated to CSRM. */
if ((*TC4_GP_BKALLOC & 0xFu) != 0u) {
wolfBoot_panic();
}
#endif
#ifdef DEBUG_UART
#ifdef TARGET_aurix_tc4xx_csrm
/* Delay to allow host-side unlock of UART during parallel boot */
{
volatile uint32_t i;
for (i = 0; i < 100000u; i++) {
}
}
#endif
uart_init();
#ifdef TARGET_aurix_tc4xx_csrm
wolfBoot_printf("Hello from TC4xx wolfBoot on CSRM: V%d\n",
WOLFBOOT_VERSION);
#else
wolfBoot_printf("Hello from TC4xx wolfBoot on TriCore CPU0: V%d\n",
WOLFBOOT_VERSION);
#endif
#endif
}
void hal_prepare_boot(void)
{
#ifdef DEBUG_UART
/* Final print, then drain so the clock switch below cannot corrupt
* in-flight characters */
wolfBoot_printf("hal_prepare_boot\n");
uart_flush();
IfxAsclin_setClockSource(TC4_UART, IfxAsclin_ClockSource_noClock);
IfxAsclin_disableModule(TC4_UART);
#endif
#ifndef TARGET_aurix_tc4xx_csrm
/* Host cores must return the clock tree to the backup clock and power the
* PLLs down, as the iLLD SSW can't handle already initialized PLLs. */
(void)IfxClock_switchToBackupClock(&IfxClock_defaultClockConfig);
#endif
}
void do_boot(const uint32_t* app_offset)
{
__asm volatile("ji %0" ::"a"(app_offset));
}
void RAMFUNCTION arch_reboot(void)
{
(void)WOLFBOOT_AURIX_RESET_REASON;
#ifdef TARGET_aurix_tc4xx_csrm
/* No reboot impl needed on CSRM yet */
while (1) {
}
#else
IfxCpu_triggerSwReset();
while (1) {
}
#endif
}
/*
* Flash HAL. Addresses arrive in the cached (0x8...) segment from the
* partition configuration. All command sequences convert to the
* non-cached alias internally.
*/
int RAMFUNCTION hal_flash_write(uint32_t address, const uint8_t* data, int size)
{
int ret = 0;
uint32_t currentAddress = address;
int remainingSize = size;
int bytesWrittenTotal = 0;
while (remainingSize > 0) {
uint32_t currentSectorAddress = GET_SECTOR_ADDR(currentAddress);
uint32_t offsetInSector = currentAddress - currentSectorAddress;
uint32_t bytesInThisSector = WOLFBOOT_SECTOR_SIZE - offsetInSector;
uint32_t page;
int needsSectorRmw = 0;
if (bytesInThisSector > (uint32_t)remainingSize) {
bytesInThisSector = remainingSize;
}
/* If any affected page already has data, read-modify-write the
* whole sector */
const uint32_t startPage = GET_PAGE_ADDR(currentAddress);
const uint32_t endPage =
GET_PAGE_ADDR(currentAddress + bytesInThisSector - 1);
for (page = startPage; page <= endPage; page += TC4_PFLASH_PAGE_SIZE) {
int erased = flashIsPageErased(page);
if (erased < 0) {
return -1;
}
if (erased == 0) {
needsSectorRmw = 1;
break;
}
}
if (needsSectorRmw) {
cacheSector(currentSectorAddress);
ret = hal_flash_erase(currentSectorAddress, WOLFBOOT_SECTOR_SIZE);
if (ret != 0) {
break;
}
memcpy((uint8_t*)sectorBuffer + offsetInSector,
data + bytesWrittenTotal, bytesInThisSector);
programCachedSector(currentSectorAddress);
}
else {
ret = programBytesToErasedFlash(
currentAddress, data + bytesWrittenTotal, bytesInThisSector);
if (ret != 0) {
break;
}
}
bytesWrittenTotal += bytesInThisSector;
currentAddress += bytesInThisSector;
remainingSize -= bytesInThisSector;
}
return ret;
}
int RAMFUNCTION hal_flash_erase(uint32_t address, int len)
{
uint32_t currentSectorAddr;
uint32_t startSectorAddr;
uint32_t endAddress;
uint32_t endSectorAddr;
int ret = 0;
if (len <= 0) {
return 0;
}
startSectorAddr = GET_SECTOR_ADDR(address);
endAddress = address + len - 1;
endSectorAddr = GET_SECTOR_ADDR(endAddress);
for (currentSectorAddr = startSectorAddr;
currentSectorAddr <= endSectorAddr;
currentSectorAddr += WOLFBOOT_SECTOR_SIZE) {
const int isFirstSector = (currentSectorAddr == startSectorAddr);
const int isLastSector = (currentSectorAddr == endSectorAddr);
const int isPartialStart = isFirstSector && (address > startSectorAddr);
const int isPartialEnd =
isLastSector &&
(endAddress < (endSectorAddr + WOLFBOOT_SECTOR_SIZE - 1));
if (isPartialStart || isPartialEnd) {
/* Partial sector: read-modify-write with the target range
* filled with the erased value */
uint32_t eraseStartOffset =
isPartialStart ? (address - currentSectorAddr) : 0;
uint32_t eraseEndOffset = isPartialEnd
? (endAddress - currentSectorAddr)
: (WOLFBOOT_SECTOR_SIZE - 1);
uint32_t eraseLen = eraseEndOffset - eraseStartOffset + 1;
uint32_t i;
cacheSector(currentSectorAddr);
for (i = 0; i < eraseLen; i++) {
((uint8_t*)sectorBuffer)[eraseStartOffset + i] =
FLASH_BYTE_ERASED;
}
if (flashEraseSector(currentSectorAddr) != 0) {
ret = -1;
break;
}
programCachedSector(currentSectorAddr);
}
else {
if (flashEraseSector(currentSectorAddr) != 0) {
ret = -1;
break;
}
}
}
return ret;
}
void RAMFUNCTION hal_flash_unlock(void) {}
void RAMFUNCTION hal_flash_lock(void) {}
int RAMFUNCTION ext_flash_write(uintptr_t address, const uint8_t* data, int len)
{
return hal_flash_write((uint32_t)address, data, len);
}
/* Reads flash, spoofing the erased-byte value for erased pages
* (reading them directly would raise an uncorrectable ECC bus error).
* Returns the number of bytes read, or -1 on error. */
int RAMFUNCTION ext_flash_read(uintptr_t address, uint8_t* data, int len)
{
int bytesRead = 0;
while (bytesRead < len) {
uint32_t pageAddress = GET_PAGE_ADDR(address);
uint32_t offset = address % TC4_PFLASH_PAGE_SIZE;
uint32_t bytesInThisPage = TC4_PFLASH_PAGE_SIZE - offset;
int erased;
if (bytesInThisPage > (uint32_t)(len - bytesRead)) {
bytesInThisPage = len - bytesRead;
}
erased = flashIsPageErased(pageAddress);
if (erased < 0) {
return -1;
}
if (erased == 1) {
uint32_t i;
for (i = 0; i < bytesInThisPage; i++) {
data[bytesRead + i] = FLASH_BYTE_ERASED;
}
}
else {
flashRead(address, data + bytesRead, bytesInThisPage);
}
address += bytesInThisPage;
bytesRead += bytesInThisPage;
}
return bytesRead;
}
int RAMFUNCTION ext_flash_erase(uintptr_t address, int len)
{
return hal_flash_erase((uint32_t)address, len);
}
void RAMFUNCTION ext_flash_lock(void)
{
hal_flash_lock();
}
void RAMFUNCTION ext_flash_unlock(void)
{
hal_flash_unlock();
}
#ifdef WOLFBOOT_ENABLE_WOLFHSM_CLIENT
/* wolfHSM client connection over the port shared-memory transport. */
/* Nonzero hardware setup return code for debugger inspection. */
volatile int g_tc4_hsmc_hw_rc;
/* CPU0 hardware setup for HsmHost transport. */
static int tc4_hsmc_hw_init(void)
{
{
IfxApApu_ApuConfig apConfig;
IfxApApu_initConfig(&apConfig);
const unsigned long srcTagMask =
(1UL << IfxApProt_TagId_cpu0d) | (1UL << IfxApProt_TagId_cpu0ds) |
(1UL << IfxApProt_TagId_cpu1d) | (1UL << IfxApProt_TagId_cpu1ds) |
(1UL << IfxApProt_TagId_cpucsd) | (1UL << IfxApProt_TagId_cpucsds);
apConfig.wraTagId = srcTagMask;
apConfig.rdaTagId = srcTagMask;
apConfig.wrbTagId = 0U;
apConfig.rdbTagId = 0U;
IfxSrc_configureAccessToSrcs(&apConfig);
}
/* Probe SR0 to confirm SRC ACCEN writes are enabled. */
SRC_GPSR4_SR0.U = 0x00006014u;
if (((SRC_GPSR4_SR0.U >> 12) & 0xFu) != 6u) {
return -1;
}
if (tchsm_SprApu_OpenDspr() != 0u) {
return -2;
}
return 0;
}
int hal_hsm_init_connect(void)
{
int rc;
/* The S2H wake ISR needs interrupts. */
IfxCpu_enableInterrupts();
rc = tc4_hsmc_hw_init();
if (rc != 0) {
g_tc4_hsmc_hw_rc = rc;
return rc;
}
tchsm_client_init(TCHSM_HSMHOST_CLIENT_APP0);
rc = tchsm_client_wait_ready(TCHSM_HSMHOST_CLIENT_APP0, 10000u);
if (rc != WH_ERROR_OK) {
return rc;
}
rc = wh_Client_Init(&hsmClientCtx,
tchsm_client_get_config(TCHSM_HSMHOST_CLIENT_APP0));
if (rc != WH_ERROR_OK) {
return rc;
}
return wh_Client_CommInit(&hsmClientCtx, NULL, NULL);
}
int hal_hsm_disconnect(void)
{
int rc = wh_Client_CommClose(&hsmClientCtx);
int rc2 = wh_Client_Cleanup(&hsmClientCtx);
return (rc != WH_ERROR_OK) ? rc : rc2;
}
#endif /* WOLFBOOT_ENABLE_WOLFHSM_CLIENT */

View File

@ -0,0 +1,23 @@
/* aurix_tc4xx_csrm.c
*
* Copyright (C) 2014-2026 wolfSSL Inc.
*
* This file is part of wolfBoot.
*
* wolfBoot is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* wolfBoot is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with wolfBoot. If not, see <http://www.gnu.org/licenses/>.
*/
/* TC4xx CSRM core (TriCore CPU6). The build defines TARGET_aurix_tc4xx_csrm,
* which selects the CSRM paths inside the shared TC4xx HAL. */
#include "aurix_tc4xx.c"

@ -1 +1 @@
Subproject commit db9a4e00cadccae36df4564784df4ea030a3ebf6 Subproject commit 86dd6df04572b5d457da4a86f12750b93cf83bf4

View File

@ -1295,6 +1295,52 @@ ifneq (,$(filter aurix_tc3xx aurix_tc3xx_hsm,$(TARGET)))
endif endif
endif endif
ifneq (,$(filter aurix_tc4xx aurix_tc4xx_csrm,$(TARGET)))
# TC4 startup tables miss some sections emitted by -fdata-sections.
CFLAGS:=$(filter-out -fdata-sections,$(CFLAGS))
# Flash helpers run from PSPR.
# Limit __WOLFBOOT to objects that define RAMFUNCTION helpers.
../hal/$(TARGET).o: CFLAGS+=-DRAM_CODE -D__WOLFBOOT
../test-app/libwolfboot.o: CFLAGS+=-DRAM_CODE -D__WOLFBOOT
ifeq ($(TARGET),aurix_tc4xx_csrm)
# CSRM app uses the shared startup and driver objects.
APP_OBJS += $(TC4_LLD_SRCS:.c=.o)
APP_OBJS += $(TC4_WB_DIR)/csrm/Cfg_Ssw/Ifx_Cfg_Ssw.o
# CSRM app linker script ships with the port.
LSCRIPT_TEMPLATE = $(TC4_WB_DIR)/csrm/tc4cs_app.ld
else
# Host test-app uses patched iLLD startup and drivers from the TC4 port.
# Drop Ifx_Ssw_Tc0.o and replace with patched aurix_tc4xx_ssw_tc0.o below
APP_OBJS += $(filter-out %/Ifx_Ssw_Tc0.o,$(TC4_LLD_SRCS:.c=.o))
APP_OBJS += $(TC4_WB_DIR)/Cfg_Ssw/Ifx_Cfg_Ssw.o
APP_OBJS += aurix_tc4xx_ssw_tc0.o
# Host app linker script ships with the port.
LSCRIPT_TEMPLATE = $(TC4_WB_DIR)/tc4tc_app.ld
endif
# TC4 wolfHSM port objects used by the HAL.
ifeq ($(WOLFHSM_CLIENT),1)
APP_OBJS += $(WOLFHSM_INFINEON_TC4XX)/port/tchsm_hsmhost.o \
$(WOLFHSM_INFINEON_TC4XX)/port/client/tchsm_client.o \
$(WOLFHSM_INFINEON_TC4XX)/port/client/tchsm_hh_host.o \
$(WOLFHSM_INFINEON_TC4XX)/port/client/tchsm_spr_apu.o \
$(WOLFHSM_INFINEON_TC4XX)/port/client/tchsm_dma_client.o \
$(WOLFHSM_INFINEON_TC4XX)/port/client/tchsm_time.o \
$(WOLFBOOT_LIB_WOLFHSM)/src/wh_transport_mem.o
endif
# Build Ifx_Ssw_Tc0.c a second time as aurix_tc4xx_ssw_tc0.o with the
# hypervisor exit compiled out, since wolfBoot already ran it before
# jumping to the app. The new name keeps it from conflicting with the
# bootloader's Ifx_Ssw_Tc0.o, which is built from the same file
aurix_tc4xx_ssw_tc0.o: $(TC4_LLD_DIR)/Infra/Ssw/TC4xx/Tricore/Ifx_Ssw_Tc0.c
@echo "\t[CC-APP] $@"
$(Q)$(CC) $(CFLAGS) -DIFX_CFG_SSW_SKIP_DISABLE_VIRTUALIZATION -c -o $@ $<
# Default goal for argument-less sub-makes.
.DEFAULT_GOAL := image.bin
endif
# On PPC64 (e5500/e6500) arch.mk turns on PPC32 SHA asm for the bootloader's # 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 # image-verify link; strip it from the test-app's wolfCrypt so PPC_ASM alone
# controls the app's AES/SHA asm. # controls the app's AES/SHA asm.

View File

@ -0,0 +1,121 @@
/* app_aurix_tc4xx.c
*
* Copyright (C) 2014-2026 wolfSSL Inc.
*
* This file is part of wolfBoot.
*
* wolfBoot is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* wolfBoot is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with wolfBoot. If not, see <http://www.gnu.org/licenses/>.
*/
/* wolfBoot test app for AURIX TC4xx.
* Host mode (TARGET=aurix_tc4xx) runs on CPU0.
* CSRM mode (TARGET=aurix_tc4xx_csrm, see app_aurix_tc4xx_csrm.c) runs
* on CPU6.
* Flash helpers run from PSPR. */
#if defined(TARGET_aurix_tc4xx) || defined(TARGET_aurix_tc4xx_csrm)
#include <stdint.h>
#include <string.h>
#include "target.h"
#include "printf.h"
#include "hal.h"
#include "wolfboot/wolfboot.h"
#ifdef WOLFBOOT_ENABLE_WOLFHSM_CLIENT
#include "wolfhsm/wh_client.h"
/* Defined by the port client glue. */
extern whClientContext hsmClientCtx;
#endif
#define BASE_FW_VERSION 1
/* Empty _init for the SSW C init hook. */
void _init(void) {}
/* Hang on flash HAL faults. */
void wolfBoot_panic(void)
{
while (1) {
__asm volatile("nop");
}
}
/* Entry after C runtime init. */
#ifdef TARGET_aurix_tc4xx_csrm
void core6_main(void)
#else
void core0_main(void)
#endif
{
#ifdef DEBUG_UART
uart_init();
#endif
#ifdef TARGET_aurix_tc4xx_csrm
wolfBoot_printf("TC4xx CSRM Test Application\n");
#else
wolfBoot_printf("TC4xx Test Application\n");
#endif
wolfBoot_printf("Version: %d\n", wolfBoot_current_firmware_version());
if (wolfBoot_current_firmware_version() <= BASE_FW_VERSION) {
/* Stage the update from base firmware. */
wolfBoot_update_trigger();
}
else {
/* Confirm updated firmware. */
wolfBoot_success();
}
#ifdef WOLFBOOT_ENABLE_WOLFHSM_CLIENT
/* Full-system echo through the wolfHSM server. */
{
int rc;
const char echoMsg[] = "wolfHSM echo test";
char echoResp[sizeof(echoMsg)];
uint16_t echoRespLen = 0;
rc = hal_hsm_init_connect();
if (rc == 0) {
wolfBoot_printf("wolfHSM Echo: sending %d bytes\n",
sizeof(echoMsg));
rc = wh_Client_Echo(&hsmClientCtx, sizeof(echoMsg), echoMsg,
&echoRespLen, echoResp);
if (rc != 0) {
wolfBoot_printf("wolfHSM Echo test failed: %d\n", rc);
}
else if ((echoRespLen != sizeof(echoMsg)) ||
(memcmp(echoResp, echoMsg, sizeof(echoMsg)) != 0)) {
/* The reply must match what was sent, byte for byte. */
wolfBoot_printf("wolfHSM Echo mismatch: received %d bytes\n",
echoRespLen);
}
else {
wolfBoot_printf("wolfHSM Echo success: received %d bytes\n",
echoRespLen);
}
hal_hsm_disconnect();
}
else {
wolfBoot_printf("HSM connect failed: %d\n", rc);
}
}
#endif
/* Main application loop. */
while (1) {
/* Spin forever. */
}
}
#endif /* TARGET_aurix_tc4xx || TARGET_aurix_tc4xx_csrm */

View File

@ -0,0 +1,22 @@
/* app_aurix_tc4xx_csrm.c
*
* Copyright (C) 2014-2026 wolfSSL Inc.
*
* This file is part of wolfBoot.
*
* wolfBoot is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* wolfBoot is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with wolfBoot. If not, see <http://www.gnu.org/licenses/>.
*/
/* TC4xx CSRM core build of the test application; see app_aurix_tc4xx.c. */
#include "app_aurix_tc4xx.c"

View File

@ -0,0 +1,9 @@
# NVM config for whnvmtool.
#
# Key format
# key <clientId> <keyId> <access> <flags> <label> <file>
# WH_NVM_FLAGS_USAGE_VERIFY is 0x100.
#
# clientId matches WOLFHSM_CLIENT_ID.
# keyId matches hsmKeyIdPubKey and TCHSM_CFG_CROSS_VERIFY_KEY_ID.
key 0x1 0xFF 0xFF 0x100 "wolfBoot Pubkey" wolfboot_signing_private_key_pub.der