Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -494,3 +494,5 @@ tools/unit-tests/zynq_write_extract.h
tools/unit-tests/unit-sign-header-failure
tools/unit-tests/unit-sign-hybrid-keyload
tools/unit-tests/unit-update-ram-uboot
# TI cl2000 (ARCH=C2000) intermediate assembly listings left in the repo root
/*.asm
19 changes: 18 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@ ifneq ($(LIBERO_FPGA_CONFIG_DIR),)
endif

CFLAGS:=-D"__WOLFBOOT"
# gcc/clang warning flags; the TI cl2000 driver (ARCH=C2000) rejects them.
ifneq ($(ARCH),C2000)
CFLAGS+=-Werror -Wextra -Wno-array-bounds
endif
LSCRIPT:=config/target.ld
LSCRIPT_FLAGS:=
LDFLAGS:=
Expand Down Expand Up @@ -238,9 +241,12 @@ $(WOLFHSM_OBJS): CFLAGS += -Wno-error=unused-parameter

CFLAGS+= \
-I"." -I"include/" -I"$(WOLFBOOT_LIB_WOLFSSL)" \
-Wno-array-bounds \
-D"WOLFSSL_USER_SETTINGS" \
-D"WOLFTPM_USER_SETTINGS"
# -Wno-array-bounds is a gcc/clang option; the TI cl2000 driver rejects it.
ifneq ($(ARCH),C2000)
CFLAGS+=-Wno-array-bounds
endif
CFLAGS+=$(WOLFPSA_CFLAGS)

# Setup default optimizations (for GCC)
Expand All @@ -260,6 +266,10 @@ endif
ifeq ($(TARGET),ti_hercules)
LSCRIPT_FLAGS+=--run_linker $(LSCRIPT)
endif
ifeq ($(ARCH),C2000)
# cl2000 enters link mode via -z (in LDFLAGS); the .cmd is a positional arg.
LSCRIPT_FLAGS+=$(LSCRIPT)
endif
ifeq ($(ARCH),AURIX_TC3)
ifneq ($(USE_GCC_HEADLESS),1)
LSCRIPT_FLAGS+=-T $(LSCRIPT)
Expand Down Expand Up @@ -377,6 +387,12 @@ ifeq ($(TARGET),tegra234)
MAIN_TARGET:=wolfboot.bin test-app/image_v1_signed.bin
endif

ifeq ($(TARGET),f28p55x)
# C28x flash is word-addressed; DSLite loads the cl2000 .out (ELF) directly.
# No objcopy / no flat .bin.
MAIN_TARGET:=wolfboot.elf
endif

ifeq ($(TARGET),sim)
CFLAGS+=-fno-pie
LDFLAGS+=-no-pie
Expand Down Expand Up @@ -722,6 +738,7 @@ keys: $(PRIVATE_KEY)
clean:
$(Q)rm -f src/*.o hal/*.o hal/spi/*.o hal/uart/*.o test-app/*.o src/x86/*.o
$(Q)rm -f src/wolfboot_tz_nsc.o
$(Q)rm -f *.asm # TI cl2000 (ARCH=C2000) intermediate listings in repo root
$(Q)rm -f $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/*.o $(WOLFBOOT_LIB_WOLFTPM)/src/*.o $(WOLFBOOT_LIB_WOLFTPM)/src/fwtpm/*.o $(WOLFBOOT_LIB_WOLFTPM)/hal/*.o $(WOLFBOOT_LIB_WOLFTPM)/examples/pcr/*.o
$(Q)rm -f $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/port/Renesas/*.o
$(Q)rm -f wolfboot.bin wolfboot.elf wolfboot.map test-update.rom wolfboot.hex wolfboot.srec factory.srec
Expand Down
84 changes: 80 additions & 4 deletions arch.mk
Original file line number Diff line number Diff line change
Expand Up @@ -1083,10 +1083,25 @@ ifeq ($(ARCH),RISCV64)

ifneq ($(NO_ASM),1)
CFLAGS+=-DWOLFSSL_RISCV_ASM
WOLFCRYPT_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
# wolfSSL moved this port to wolfcrypt/src/port/riscv64/ and split each
# primitive into a generated <name>-asm.S plus a <name>-asm_c.c. Only one
# is live: the .S builds unless WOLFSSL_RISCV_ASM_INLINE is defined, which
# wolfBoot does not define, and the _asm_c.c compiles to an empty
# translation unit in that case. Pick whichever layout the pinned
# submodule actually has so this builds against wolfSSL before and after
# the move.
RISCV_ASM_DIR := $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/port/riscv64
ifneq ($(wildcard $(RISCV_ASM_DIR)/riscv-64-sha256-asm.S),)
WOLFCRYPT_OBJS+=$(RISCV_ASM_DIR)/riscv-64-sha256-asm.o \
$(RISCV_ASM_DIR)/riscv-64-sha512-asm.o \
$(RISCV_ASM_DIR)/riscv-64-sha3-asm.o \
$(RISCV_ASM_DIR)/riscv-64-aes-asm.o
else
WOLFCRYPT_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
endif

Expand Down Expand Up @@ -2065,6 +2080,67 @@ ifeq ($(ARCH),sim)
endif
endif

# TI C2000 C28x DSP (TMS320F28P550SJ / LAUNCHXL-F28P55X), cl2000 toolchain.
# Word-addressed, CHAR_BIT==16. Modeled on the ti_hercules (armcl) TI-CGT flow.
ifeq ($(ARCH),C2000)
# cl2000 is not gcc: turn off the gcc/headless CFLAGS+LDFLAGS blocks that
# follow the arch.mk include (Makefile ~line 247) before they are evaluated.
USE_GCC:=0
USE_GCC_HEADLESS:=0

C2000WARE?=$(HOME)/ti/C2000Ware_26_01_00_00
ifeq ($(CGT_ROOT),)
$(error Set CGT_ROOT to a TI C2000 codegen install (the dir with bin/cl2000))
endif
C2000_DEV:=$(C2000WARE)/device_support/f28p55x
C2000_DRV:=$(C2000WARE)/driverlib/f28p55x/driverlib
C2000_FAPI:=$(C2000WARE)/libraries/flash_api/f28p55x

CC=$(CGT_ROOT)/bin/cl2000
LD=$(CGT_ROOT)/bin/cl2000
AS=$(CGT_ROOT)/bin/cl2000
AR=$(CGT_ROOT)/bin/ar2000
OUTPUT_FLAG=--output_file

# --float_support/--abi must match the prebuilt driverlib.lib + Fapi lib (EABI).
ARCH_FLAGS=-v28 --float_support=fpu32 --tmu_support=tmu1 --abi=eabi \
--gen_func_subsections=on
# Set the level here so options.mk emits -O2 (matching cl2000) instead of its
# default gcc-only -Os, which would otherwise be appended after our flags.
OPTIMIZATION_LEVEL=2
CFLAGS+=$(ARCH_FLAGS) -D_LAUNCHXL_F28P55X -D_FLASH \
-I$(CGT_ROOT)/include -I$(C2000_DRV) \
-I$(C2000_DEV)/common/include -I$(C2000_DEV)/headers/include \
-I$(C2000_FAPI)/include -I$(C2000_FAPI)/include/FlashAPI
# The C28x has no 8-bit type, so ISO <stdint.h> omits int8_t/uint8_t; supply
# them (as 16-bit) via a preinclude for every TU. #303 is the harmless
# "typedef already declared (same type)" clash with driverlib's hw_types.h.
# #169 is the expected uint8_t*(=uint16_t*) vs wolfSSL byte*(=unsigned char*)
# pointer mismatch; both are 16-bit cells holding one octet, so it is safe.
CFLAGS+=--preinclude=c2000_stdint.h --diag_suppress=303 --diag_suppress=169
LDFLAGS+=$(ARCH_FLAGS) -z --reread_libs --warn_sections \
-i$(CGT_ROOT)/lib -i$(C2000_DRV)/ccs/Release -i$(C2000_FAPI)/lib \
-m wolfboot.map
LD_START_GROUP:=
LD_END_GROUP:=-l driverlib.lib -l FAPI_F28P55x_EABI_v4.00.00.lib -l libc.a
ARCH_FLASH_OFFSET=0x80000

# TI device startup: reset codestart -> _c_int00 (RTS) -> main.
OBJS+=$(C2000_DEV)/common/source/device.o
OBJS+=$(C2000_DEV)/common/source/f28p55x_codestartbranch.o
OBJS+=src/boot_c2000.o

ifeq ($(SPMATH),1)
# SECP256R1 fast SP path (wide-byte hand-patched octet masks live here).
MATH_OBJS+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/sp_c32.o
endif

# TI assembler sources use the .asm suffix.
%.o:%.asm
@echo "\t[AS-C2000] $@"
$(Q)$(CC) $(CFLAGS) -c $(OUTPUT_FLAG) $@ $^
endif

# Infineon AURIX Tricore
ifeq ($(ARCH), AURIX_TC3)
# TC3xx specific
Expand Down
54 changes: 54 additions & 0 deletions config/examples/f28p55x.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# TI LAUNCHXL-F28P55X (TMS320F28P550SJ, C2000 C28x DSP) - secure-boot MVP
#
# The C28x is a word-addressed, CHAR_BIT==16 DSP built with the TI cl2000
# compiler. wolfBoot runs from flash bank0 and XIP-boots a signed application
# resident in bank1. See docs/Targets.md and the port notes in hal/f28p55x.c.
#
# Build (point CGT_ROOT at a TI C2000 codegen install, C2000WARE at C2000Ware):
# cp config/examples/f28p55x.config .config
# make CGT_ROOT=$HOME/ti/ccs<ver>/ccs/tools/compiler/ti-cgt-c2000_<ver> \
# C2000WARE=$HOME/ti/C2000Ware_26_01_00_00
#
# Flash offset (bank0 codestart) is fixed by the arch in arch.mk:
# ARCH_FLASH_OFFSET=0x80000

ARCH?=C2000
TARGET?=f28p55x
SIGN?=ECC256
HASH?=SHA256
DEBUG?=0
# Route wolfBoot_printf to SCIA (GPIO28/29 -> XDS110 virtual COM, 115200 8N1)
DEBUG_UART?=1
VTOR?=0
CORTEX_M0?=0
NO_ASM?=1
NO_MPU?=1
EXT_FLASH?=0
SPI_FLASH?=0
ALLOW_DOWNGRADE?=0
# Fapi programs whole flash words with ECC; single-byte trailer writes are not
# possible, so use the whole-sector read-modify-write cache path.
NVM_FLASH_WRITEONCE?=1
WOLFBOOT_VERSION?=0
V?=0
# ECC P-256 verify via SP single-precision math (32-bit words, sp_c32.c).
SPMATH?=1
# HAL flash program/erase (Fapi) must execute from RAM.
RAM_CODE?=1
DUALBANK_SWAP?=0

# Flash bank map (word addresses; hardware banks are 0x80000, 0xA0000, 0xC0000,
# 0xE0000, 0x100000). wolfBoot owns bank0; BOOT is bank1, UPDATE bank2, SWAP
# bank3 (UPDATE/SWAP are declared for the phase-2 A/B update path and are not
# exercised by the MVP verify+jump). The signed app's codestart is linked at
# WOLFBOOT_PARTITION_BOOT_ADDRESS + IMAGE_HEADER_SIZE = 0xA0100.
#
# WOLFBOOT_SECTOR_SIZE must be >= IMAGE_HEADER_SIZE and match the Fapi erase
# granularity. Confirm the 2KB F28P55x sector in words against the Fapi sector
# table before relying on the phase-2 erase/trailer path; 0x800 is a safe
# conservative value for the MVP (no erase/write on the boot-critical path).
WOLFBOOT_SECTOR_SIZE?=0x800
WOLFBOOT_PARTITION_SIZE?=0x20000
WOLFBOOT_PARTITION_BOOT_ADDRESS?=0xA0000
WOLFBOOT_PARTITION_UPDATE_ADDRESS?=0xC0000
WOLFBOOT_PARTITION_SWAP_ADDRESS?=0xE0000
43 changes: 43 additions & 0 deletions docs/Targets.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ This README describes configuration of supported targets.
* [STM32L5](#stm32l5)
* [STM32U5](#stm32u5)
* [STM32WB55](#stm32wb55)
* [TI C2000 C28x (LAUNCHXL-F28P55X)](#ti-c2000-c28x-launchxl-f28p55x)
* [TI Hercules TMS570LC435](#ti-hercules-tms570lc435)
* [Vorago VA416x0](#vorago-va416x0)
* [Xilinx Zynq UltraScale](#xilinx-zynq-ultrascale)
Expand Down Expand Up @@ -8977,3 +8978,45 @@ Boot success marked. Version: 1
| `FLAGS_HOME` | Keep boot flags in internal flash (required when `EXT_FLASH=1`). |
| `MAX3266X_TPU` | Enable TPU hardware SHA256 acceleration (requires `MSDK_DIR`). |
| `MAX3266X_OLD` | Build TPU acceleration against the older, deprecated Maxim SDK tree instead of the modern MSDK. |

## TI C2000 C28x (LAUNCHXL-F28P55X)

wolfBoot runs on the Texas Instruments C2000 C28x DSP (TMS320F28P550SJ, 150 MHz) as a secure execute-in-place (XIP) bootloader. The C28x is word-addressed with `CHAR_BIT == 16` (no 8-bit type -- each octet occupies one 16-bit cell), built with the TI `cl2000` toolchain against wolfSSL's wide-byte (`CHAR_BIT != 8`) support.

### Flash layout

wolfBoot owns flash bank0 (`0x80000`); the signed application lives in the BOOT partition at bank1 (`0xA0000`). Because an octet-per-cell header and a native-word executable cannot share one representation, the BOOT partition uses a split layout: the 256-cell image header is stored one octet per 16-bit cell (so wolfBoot's generic octet parser and hash work byte-identically to the host), and the firmware follows at `0xA0100` as native 16-bit words that execute in place.

| Region | Address | Contents |
|--------|---------|----------|
| wolfBoot (bank0) | `0x80000` | bootloader code + keystore |
| BOOT header | `0xA0000` | 256-cell signed header (one octet per cell) |
| BOOT firmware | `0xA0100` | native XIP application |

### Build

```
cp config/examples/f28p55x.config .config
make CGT_ROOT=/path/to/ti-cgt-c2000 C2000WARE=/path/to/C2000Ware
```

This produces `wolfboot.elf` (the cl2000 `.out`); DSLite loads it directly, since C28x flash is word-addressed there is no objcopy / flat `.bin` step.

### Sign and flash the application

The test application (`test-app/app_f28p55x.c`) is linked to execute in place at `0xA0100`. `test-app/f28p55x_sign.sh` documents the flow: compile the XIP app, extract its firmware as the host octet stream, sign it (ECC P-256 + SHA-256), and emit the octet-per-cell header blob for `0xA0000`. Flash `wolfboot.elf` and the application image with DSLite over the onboard XDS110.

### Boot mode

The C28x boot ROM selects its boot source before any application code runs, so the device must be told to boot from flash. Under a debug session CCS/DSLite (via the device GEL) writes a volatile flash-boot override -- `EMU_BOOTPIN_KEY (0xD00) = 0x5AFFFFFF`, `EMU_BOOTPIN_CONFIG (0xD04) = 0x0003` (boot mode 3, flash entry `0x080000`) -- so wolfBoot boots from `0x80000` whenever a debugger has connected. That override is volatile and is not present on a bare power-on-reset. For **standalone** flash boot the device's persistent boot mode must be provisioned to flash (boot mode `0x03`) via the DCSM boot OTP, or set with the board's boot-mode straps where available; until then a bare power-up waits in the boot ROM. The SCIA console (GPIO28/29, 115200 8N1) is on the XDS110 virtual COM port; a live debug session garbles that backchannel, so read it with the probe detached.

### Configuration options

| Option | Description |
|--------|-------------|
| `SIGN=ECC256` / `HASH=SHA256` | Signature and hash for the secure-boot MVP. |
| `RAM_CODE` | **Required.** Flash program/erase (TI Fapi) runs from RAM. |
| `NVM_FLASH_WRITEONCE` | Flash is written once between erases. |
| `DEBUG` | Enables verbose boot progress and a JTAG-readable survive-log mirror (`g_log`) for bring-up. |

A/B update / rollback is a follow-on: the partitions are declared, but the update path (flash erase/write, swap, trailer) is not yet wide-byte-hardened.
Loading
Loading