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
12 changes: 11 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -451,11 +451,20 @@ test-app/image_v1_signed.bin: $(BOOT_IMG) keytools_check
@echo "\t[SIGN] $(BOOT_IMG)"
@echo "\tSECONDARY_SIGN_OPTIONS=$(SECONDARY_SIGN_OPTIONS)"
@echo "\tSECONDARY_PRIVATE_KEY=$(SECONDARY_PRIVATE_KEY)"

ifeq ($(STRIP_ELF),1)
@echo "\t[STRIP] $(BOOT_IMG)"
$(Q)$(OBJCOPY) --strip-debug $(BOOT_IMG) $(BOOT_IMG).stripped
$(Q)(test $(SIGN) = NONE) || $(SIGN_ENV) $(SIGN_TOOL) $(SIGN_OPTIONS) \
$(SECONDARY_SIGN_OPTIONS) $(BOOT_IMG).stripped $(PRIVATE_KEY) \
$(SECONDARY_PRIVATE_KEY) 1 || true
$(Q)(test $(SIGN) = NONE) && $(SIGN_ENV) $(SIGN_TOOL) $(SIGN_OPTIONS) $(BOOT_IMG).stripped 1 || true
$(Q)mv test-app/image.elf_v1_signed.bin test-app/image_v1_signed.bin
Comment thread
dgarske marked this conversation as resolved.
else
$(Q)(test $(SIGN) = NONE) || $(SIGN_ENV) $(SIGN_TOOL) $(SIGN_OPTIONS) \
$(SECONDARY_SIGN_OPTIONS) $(BOOT_IMG) $(PRIVATE_KEY) \
$(SECONDARY_PRIVATE_KEY) 1 || true
$(Q)(test $(SIGN) = NONE) && $(SIGN_ENV) $(SIGN_TOOL) $(SIGN_OPTIONS) $(BOOT_IMG) 1 || true
endif

test-app/image.elf: wolfboot.elf
$(Q)$(MAKE) -C test-app WOLFBOOT_ROOT="$(WOLFBOOT_ROOT)" ELF_FLASH_SCATTER="$(ELF_FLASH_SCATTER)" image.elf
Expand Down Expand Up @@ -537,6 +546,7 @@ $(LSCRIPT): $(LSCRIPT_IN) FORCE
sed -e "s/@WOLFBOOT_LOAD_BASE@/$(WOLFBOOT_LOAD_BASE)/g" | \
sed -e "s/@BOOTLOADER_START@/$(BOOTLOADER_START)/g" | \
sed -e "s/@IMAGE_HEADER_SIZE@/$(IMAGE_HEADER_SIZE)/g" | \
sed -e "s/@WOLFBOOT_LOAD_ADDRESS@/$(WOLFBOOT_LOAD_ADDRESS)/g" | \
sed -e "s/@FSP_S_LOAD_BASE@/$(FSP_S_LOAD_BASE)/g" | \
sed -e "s/@WOLFBOOT_L2LIM_SIZE@/$(WOLFBOOT_L2LIM_SIZE)/g" | \
sed -e "s/@L2SRAM_ADDR@/$(L2SRAM_ADDR)/g" \
Expand Down
38 changes: 28 additions & 10 deletions config/examples/polarfire_mpfs250_m_qspi.config
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,30 @@ WOLFTPM?=0
ELF?=1
#DEBUG_ELF?=1

# Strip debug symbols from test-app ELF before signing.
# Required for M-mode: unstripped ELF (~150KB) is too large for L2 Scratch.
# Stripped ELF is typically ~5KB.
STRIP_ELF?=1

# Watchdog timer configuration (default: disabled)
# When commented out, the WDT is disabled in hal_init() and re-enabled
# with the boot ROM default in hal_prepare_boot() before do_boot.
# Uncomment -DWATCHDOG to keep the WDT enabled with a generous timeout
# for the duration of wolfBoot. Verify is bounded at ~5s; default 30s
# avoids the need to pet the WDT during long ECDSA verify.
#CFLAGS_EXTRA+=-DWATCHDOG
#CFLAGS_EXTRA+=-DWATCHDOG_TIMEOUT_MS=30000

OPTIMIZATION_LEVEL=1

# M-Mode Configuration
# Runs on E51 core in Machine Mode from L2 SRAM
RISCV_MMODE?=1

# Stack size per hart (reduced for L2 SRAM constraints)
CFLAGS_EXTRA+=-DSTACK_SIZE_PER_HART=8192
# Stack size per hart: set to 0 for M-mode (only E51/hart 0 runs;
# secondary harts park in eNVM WFI loop and never use L2 Scratch stacks).
# The linker script (mpfs250-m.ld) uses STACK_SIZE_PER_HART = 0 to match.
CFLAGS_EXTRA+=-DSTACK_SIZE_PER_HART=0

# E51 core lacks RISC-V crypto extensions (Zknh), use portable C implementations
NO_ASM?=1
Expand All @@ -57,7 +73,7 @@ SPI_FLASH?=0

# SPI Flash Controller Selection:
# MPFS_SC_SPI: Use SC QSPI Controller (0x37020100) for fabric-connected flash.
# Direct register access to System Controller's QSPI instance.
# Required for Video Kit (flash is fabric-connected, not on MSS pins).
# DEFAULT: Use MSS QSPI Controller (0x21000000) for external flash
# on MSS QSPI pins.
CFLAGS_EXTRA+=-DMPFS_SC_SPI
Expand All @@ -71,12 +87,12 @@ DISK_EMMC?=0
WOLFBOOT_ORIGIN?=0x0A000000

# Load application to L2 Scratchpad (above wolfBoot code, below stack)
# wolfBoot occupies ~40KB at 0x0A000000, stack is 64KB at top of 256KB.
# wolfBoot is ~36KB; 128KB reserved for growth headroom.
# Note: update_ram places header at (LOAD_ADDRESS - IMAGE_HEADER_SIZE),
# so offset by header size to keep header aligned.
# IMPORTANT: Strip debug symbols from test-app ELF before signing to keep
# the image small enough to fit in L2 Scratchpad (~150KB available).
WOLFBOOT_LOAD_ADDRESS?=0x0A010200
# the image small enough to fit in L2 Scratchpad (~95KB available).
WOLFBOOT_LOAD_ADDRESS?=0x0A020200

# Flash geometry (64 KB sector to match QSPI flash)
WOLFBOOT_SECTOR_SIZE?=0x10000
Expand Down Expand Up @@ -104,9 +120,11 @@ CFLAGS_EXTRA+=-DWOLFBOOT_SHA_BLOCK_SIZE=4096
# Uncomment to run test during hal_init()
#CFLAGS_EXTRA+=-DTEST_EXT_FLASH

# UART QSPI programmer (disabled by default)
# When enabled, wolfBoot prompts on UART at startup to receive a signed firmware
# image and write it to QSPI flash -- no Libero/JTAG tool required for updates.
# UART QSPI programmer (enabled for M-mode)
# In M-mode, QSPI flash is not accessible via Libero/JTAG, so this UART-based
# programmer is the primary method to load the test-app image into QSPI.
# wolfBoot prompts on UART at startup ("Press P within 3s") to receive a signed
# firmware image and write it to QSPI flash.
# Use: python3 tools/scripts/mpfs_qspi_prog.py <port> <image.bin> [qspi_offset]
# Requires EXT_FLASH=1 (already set) and DEBUG_UART=1.
UART_QSPI_PROGRAM?=0
UART_QSPI_PROGRAM?=1
23 changes: 23 additions & 0 deletions docs/Targets.md
Original file line number Diff line number Diff line change
Expand Up @@ -827,6 +827,29 @@ Key build settings that differ between configurations:
> **Note:** All configurations require `NO_ASM=1` because the MPFS250 U54/E51 cores lack RISC-V
> crypto extensions (Zknh); wolfBoot uses portable C implementations for all cryptographic operations.

### M-Mode Optional Build Flags

These flags apply to `polarfire_mpfs250_m_qspi.config` and are added via `CFLAGS_EXTRA+=-D...`.

| Flag | Default | Description |
|------|---------|-------------|
| `WATCHDOG` | undefined (disabled) | When defined, the E51 watchdog timer is **kept enabled** during wolfBoot operation with a generous timeout. When undefined, the WDT is **disabled** in `hal_init()` and re-enabled with the boot ROM default in `hal_prepare_boot()` before jumping to the application. Either way, the application receives a normal WDT. |
| `WATCHDOG_TIMEOUT_MS` | `30000` (30 s) | Watchdog timeout in milliseconds when `WATCHDOG` is defined. ECDSA P-384 verification on E51 with portable C math is bounded at ~5 s; the default 30 s avoids any need to refresh the WDT during the long verify call. |

#### Stack overflow detection

The trap handler in `src/boot_riscv.c` automatically detects stack overflow on synchronous exceptions (requires `DEBUG_BOOT`). When a trap fires with `SP < _main_hart_stack_bottom`, it prints:

```
TRAP: cause=2 epc=A000740 tval=0
sp=A02FFE8
STACK OVERFLOW: under by 24
```

This is helpful for diagnosing illegal-instruction TRAPs at random valid `.text` addresses, which are the classic signature of stack overflow corrupting the return address.

The current `STACK_SIZE` in `hal/mpfs250-m.ld` is **32 KB**. Measured peak for ECC384 + SHA384 + SPMATHALL + NO_ASM is ~6 KB (5x headroom).

### PolarFire SoC Files

`hal/mpfs250.c` - Hardware abstraction layer (UART, QSPI, SD/eMMC, multi-hart)
Expand Down
19 changes: 13 additions & 6 deletions hal/mpfs250-m.ld
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ MEMORY
}

/* Stack size for the boot hart (E51 in M-mode)
* ECC384 signature verification with sp_int needs significant stack
* for big number temporaries and point multiplication */
PROVIDE(STACK_SIZE = 64k);
* ECC384 + SHA384 + SPMATHALL + NO_ASM measured peak: ~6KB.
* 32KB provides 5x headroom. */
PROVIDE(STACK_SIZE = 32k);

SECTIONS
{
Expand Down Expand Up @@ -115,11 +115,13 @@ PROVIDE(_start_heap = _end);
*
* Stack sizes (defined in config or header):
* STACK_SIZE_PER_HART = 8192 (8KB per hart)
* STACK_SIZE = 64K (64KB for main hart E51)
* STACK_SIZE = 32K (32KB for main hart E51)
*
* Total stack area: STACK_SIZE + 4 * STACK_SIZE_PER_HART = 48KB
* Total stack area: STACK_SIZE + 4 * STACK_SIZE_PER_HART
*/
PROVIDE(STACK_SIZE_PER_HART = 8192);
/* M-mode: only E51 (hart 0) runs; secondary harts park in eNVM WFI loop.
* Set to 0 so no L2 Scratch is wasted on phantom secondary stacks. */
PROVIDE(STACK_SIZE_PER_HART = 0);

/* End of L2 scratchpad */
PROVIDE(_l2_scratch_end = ORIGIN(L2_SCRATCH) + LENGTH(L2_SCRATCH));
Expand All @@ -144,3 +146,8 @@ PROVIDE(__global_pointer$ = _global_pointer);

/* Size of text section to copy (for startup code) */
PROVIDE(_text_size = _end_text - _start_text_sram);

/* Build-time safety: ensure wolfBoot binary does not overlap image load area.
* Image header is loaded at (WOLFBOOT_LOAD_ADDRESS - IMAGE_HEADER_SIZE). */
ASSERT(_end <= @WOLFBOOT_LOAD_ADDRESS@ - @IMAGE_HEADER_SIZE@,
"ERROR: wolfBoot binary overlaps image load area! Increase WOLFBOOT_LOAD_ADDRESS")
Loading
Loading