wolfBoot/docs/compile.md

16 KiB

wolfBoot Build System Guide

Overview

wolfBoot provides a flexible build system supporting multiple embedded platforms through a modular Hardware Abstraction Layer (HAL). This guide explains the build configuration options and compilation process.

Build Configuration Methods

1. Command Line Options

Set build options directly via environment variables:

make CORTEX_M0=1

2. Configuration File (.config)

Create a persistent configuration in the root directory:

# Example .config entry
WOLFBOOT_PARTITION_BOOT_ADDRESS?=0x14000

Note: Command line options take precedence over .config entries when using ?= operator.

Configuration Setup

Generate New Configuration

# Create default configuration
make config

# Follow prompts to configure:
# - Press Enter to accept default values [shown in brackets]
# - Enter new value to override defaults

The generated .config file can be:

  • Used as default for subsequent make commands
  • Modified manually with a text editor
  • Overridden by command line options

Platform Configuration

Target Selection

Set target platform using TARGET variable:

make TARGET=stm32f4  # Default if unspecified

For supported platforms, see:

Architecture-Specific Options

Default architecture support:

  • ARM Cortex-M3/M4/M7

For other architectures:

# Cortex-M0 support
make CORTEX_M0=1

# See HAL documentation for other architecture options

Adding New Platforms

  1. Create HAL driver in hal/ directory
  2. Add corresponding linker script
  3. Implement required HAL functions

Optimization Options

Size vs Speed Tradeoffs

Assembly Optimizations

# Disable all assembly optimizations (smallest code)
make NO_ASM=1

# Disable ARM-specific optimizations only
make NO_ARM_ASM=1  # Keeps SP math optimizations

Performance Impact Example

ECC256 + SHA256 on STM32H7 (100KB image verification):

Optimization Level Configuration Size (B) Time (s) Notes
Maximum Speed SIGN=ECC256 21,836 0.583 Full assembly optimizations
Balanced SIGN=ECC256 NO_ARM_ASM=1 18,624 0.760 ECC/SP math only
Minimum Size SIGN=ECC256 NO_ASM=1 14,416 3.356 No assembly code

Note: Disabling optimizations significantly impacts boot time but reduces code size.

Flash Memory Configuration

Partition Configuration

The flash memory layout is defined in include/target.h, generated based on the following configuration parameters:

Parameter Description Usage
WOLFBOOT_SECTOR_SIZE Physical flash sector size - Minimum swap unit
- Must be largest sector size if partitions have different geometries
WOLFBOOT_PARTITION_SIZE Size of BOOT/UPDATE partitions - Same size for both partitions
- Must accommodate firmware + headers
WOLFBOOT_PARTITION_BOOT_ADDRESS Boot partition start address - Must be sector-aligned
- App starts after header (256B)
WOLFBOOT_PARTITION_UPDATE_ADDRESS Update partition start address - Physical address for internal flash
- Offset for external flash
WOLFBOOT_PARTITION_SWAP_ADDRESS Swap area start address - Used for reversible updates
- Size = one sector

Memory Layout Example

Flash Memory
+------------------------+ <- 0x00000000
|      wolfBoot         |
+------------------------+ <- WOLFBOOT_PARTITION_BOOT_ADDRESS
| Header |   Firmware   |    Boot Partition
+------------------------+ <- WOLFBOOT_PARTITION_UPDATE_ADDRESS
| Header |   Update     |    Update Partition
+------------------------+ <- WOLFBOOT_PARTITION_SWAP_ADDRESS
|        Swap           |    Swap Area (1 sector)
+------------------------+

Configuration Methods

Set parameters via:

  1. Command line:
make WOLFBOOT_SECTOR_SIZE=0x1000 WOLFBOOT_PARTITION_SIZE=0x20000
  1. .config file:
WOLFBOOT_SECTOR_SIZE?=0x1000
WOLFBOOT_PARTITION_SIZE?=0x20000

Bootloader Configuration

Digital Signature Algorithms

wolfBoot supports multiple signature algorithms with different security and performance characteristics.

Available Algorithms

Algorithm Command Key Size Performance Size Impact
Ed25519 (default) SIGN=ED25519 256-bit Good Smallest
ECDSA P-256 SIGN=ECC256 256-bit Better Medium
ECDSA P-384 SIGN=ECC384 384-bit Good Medium
ECDSA P-521 SIGN=ECC521 521-bit Good Larger
RSA-2048 SIGN=RSA2048 2048-bit Good Large
RSA-3072 SIGN=RSA3072 3072-bit Moderate Larger
RSA-4096 SIGN=RSA4096 4096-bit Moderate Largest
Ed448 SIGN=ED448 448-bit Good Medium
No Authentication SIGN=NONE N/A Best Minimal

Usage Examples

# Use Ed25519 (default)
make

# Use ECDSA P-256
make SIGN=ECC256

# Use RSA-2048
make SIGN=RSA2048

# Disable authentication
make SIGN=NONE

Key Generation

  • Each algorithm requires specific key generation tools
  • Tools available in tools/ directory
  • See Signing.md for detailed key management instructions

Warning: Using SIGN=NONE disables secure boot authentication

Advanced Features

Incremental Updates

Enable delta-based firmware updates to minimize update size and flash operations.

# Enable incremental updates
make DELTA_UPDATES=1

# Generate delta update
./tools/keytools/sign --delta old.bin new.bin key.der version

For detailed information, see Firmware Updates.

Debug Support

Enable debugging features and symbols:

make DEBUG=1

Important: Debug build increases bootloader size significantly. Ensure sufficient flash space before WOLFBOOT_PARTITION_BOOT_ADDRESS.

Interrupt Vector Configuration

Control interrupt vector table (IVT) relocation:

Option Description Use Case
Default Relocates IVT via VTOR Standard operation
VTOR=0 Disables IVT relocation - External IVT management
- Platforms without VTOR
- Custom relocation schemes
# Disable vector table relocation
make VTOR=0

Memory Management

Stack Configuration Options

wolfBoot provides flexible stack management options to accommodate different memory constraints:

Option Description Use Case
Default Stack-only operation - No dynamic allocation
- Predictable memory usage
WOLFBOOT_SMALL_STACK=1 Static memory pool - Limited RAM systems
- Dedicated bootloader RAM
WOLFBOOT_HUGE_STACK=1 Large stack allowed - Systems with ample RAM
- Complex crypto operations

Memory Usage Characteristics

  1. Default Mode

    • Uses stack for all operations
    • No dynamic memory allocation
    • Stack usage varies by algorithm
    • Predictable at compile time
  2. Small Stack Mode

    make WOLFBOOT_SMALL_STACK=1
    
    • Creates fixed-size memory pool
    • Reduces runtime stack usage
    • Uses static allocation
    • Simulates dynamic allocation
    • Suitable for RAM-constrained systems
  3. Large Stack Mode

    make WOLFBOOT_HUGE_STACK=1
    
    • Bypasses stack size checks
    • Required for some crypto configs
    • Use when RAM is abundant
    • Enables complex operations

Warning: Large stack mode may cause issues on RAM-constrained systems

Safety and Recovery Features

Firmware Backup Control

Control backup behavior during updates:

# Disable firmware backup
make DISABLE_BACKUP=1
Mode Description Use Case Risk Level
Default Creates backup copy Normal operation Safe
DISABLE_BACKUP=1 No backup created - Limited flash space
- Read-only update partition
High

Warning: Disabling backup removes fallback protection against failed updates

Flash Memory Handling

Write-Once Flash Support

For flash that doesn't support multiple writes between erases:

# Enable write-once flash support
make NVM_FLASH_WRITEONCE=1

Important Notes:

  • Required for some microcontrollers
  • Affects flag field operations
  • Compromises fail-safe swap guarantee
  • Power loss during swap may corrupt firmware
Version Control

Control firmware version enforcement:

Option Command Behavior Security Impact
Default N/A Prevents downgrades Secure
ALLOW_DOWNGRADE=1 make ALLOW_DOWNGRADE=1 Allows older versions Vulnerable to downgrade attacks

Security Warning:

  • Enabling downgrades bypasses version checks
  • May expose system to malicious downgrades
  • Use only in development/testing

External Flash Support

Overview

wolfBoot supports external flash memory for storing firmware updates and swap partitions, with configurable partition mapping and access methods.

Configuration Options

Option Description Default Usage
EXT_FLASH=1 Enable external flash No Basic external flash support
PART_UPDATE_EXT Map update to external Yes* Store updates externally
PART_SWAP_EXT Map swap to external Yes* Use external swap space
PART_BOOT_EXT Map boot to external No** For non-XIP systems
NO_XIP=1 Disable execute-in-place No For MMU systems

* When EXT_FLASH=1 ** Unless NO_XIP=1

Memory Configurations

  1. Standard External Flash

    make EXT_FLASH=1
    
    • Updates and swap in external flash
    • Boot partition in internal flash
    • Requires HAL extension
  2. Non-XIP Systems (e.g., Cortex-A)

    make EXT_FLASH=1 NO_XIP=1
    
    • All partitions in external flash
    • Images loaded to RAM for execution
    • Supports position-independent code

Implementation Requirements

  1. HAL Extension

  2. Compatibility Notes

    • Incompatible with NVM_FLASH_WRITEONCE
    • Use HAL layer for special flash handling
    • Consider word size requirements

For an example of using EXT_FLASH to bypass read restrictions, (in this case, the inability to read from erased flash due to ECC errors) on a platform with write-once flash, see the infineon tricore port.

External Memory Interfaces

SPI Flash Support

Enable SPI flash memory integration:

make EXT_FLASH=1 SPI_FLASH=1

Features:

  • Automatic ext_flash API mapping
  • Platform-specific SPI drivers
  • Multiple platform support

Implementation:

  1. Define SPI functions
  2. See examples in hal/spi/
  3. No manual ext_flash_* implementation needed

UART Bridge Support

Enable UART-based external memory access:

make EXT_FLASH=1 UART_FLASH=1

Capabilities:

  • Remote flash access
  • Neighbor system integration
  • Protocol-based communication

Requirements:

  • Compatible neighbor service
  • wolfBoot protocol support
  • UART interface availability

For detailed UART implementation, see:

Advanced Memory Features

External Partition Encryption

Enable ChaCha20 encryption for external partitions:

make EXT_FLASH=1 [SPI_FLASH=1|UART_FLASH=1]

Requirements:

  • External flash configuration
  • Pre-encrypted update images
  • ChaCha20 symmetric key setup

Compatibility:

  • Works with SPI flash
  • Works with UART bridge
  • Supports custom mappings

For implementation details, see Encrypted Partitions.

RAM-Based Flash Operations

Execute flash access code from RAM:

make RAM_CODE=1

Use Cases:

  • Avoid flash conflicts
  • Self-modifying operations
  • Flash configuration changes

Important: Required for some hardware configurations to enable flash write access.

Hardware-Assisted Updates

Enable dual-bank swap support:

make DUALBANK_SWAP=1

Features:

  • Hardware-assisted updates
  • Efficient bank switching
  • Reduced update time

Support:

  • STM32F76x series
  • STM32F77x series
  • Future platform support planned

Store UPDATE partition flags in a sector in the BOOT partition

By default, wolfBoot keeps track of the status of the update procedure to the single sectors in a specific area at the end of each partition, dedicated to store and retrieve a set of flags associated to the partition itself.

In some cases it might be helpful to store the status flags related to the UPDATE partition and its sectors in the internal flash, alongside with the same set of flags used for the BOOT partition. By compiling wolfBoot with the FLAGS_HOME=1 makefile option, the flags associated to the UPDATE partition are stored in the BOOT partition itself.

While on one hand this option slightly reduces the space available in the BOOT partition to store the firmware image, it keeps all the flags in the BOOT partition.

Flash Erase value / Flag logic inversion

By default, most NVMs set the content of erased pages to 0xFF (all ones).

Some FLASH memory models use inverted logic for erased page, setting the content to 0x00 (all zeroes) after erase.

For these special cases, the option FLAGS_INVERT = 1 can be used to modify the logic of the partition/sector flags used in wolfBoot.

You can also manually override the fill bytes using FILL_BYTE= at build-time. It default to 0xFF, but will use 0x00 if FLAGS_INVERT is set.

Note: if you are using an external FLASH (e.g. SPI) in combination with a flash with inverted logic, ensure that you store all the flags in one partition, by using the FLAGS_HOME=1 option described above.

Using One-time programmable (OTP) flash as keystore

By default, keys are directly incorporated in the firmware image. To store the keys in a separate, one-time programmable (OTP) flash memory, use the FLASH_OTP_KEYSTORE=1 option. For more information, see /docs/OTP-keystore.md.

Prefer multi-sector flash erase operations

wolfBoot HAL flash erase function must be able to handle erase lengths larger than WOLFBOOT_SECTOR_SIZE, even if the underlying flash controller does not. However, in some cases, wolfBoot defaults to iterating over a range of flash sectors and erasing them one at a time. Setting the FLASH_MULTI_SECTOR_ERASE=1 config option prevents this behavior when possible, configuring wolfBoot to instead prefer a single HAL flash erase invocation with a larger erase length versus the iterative approach. On targets where multi-sector erases are more performant, this option can be used to dramatically speed up the image swap procedure.

Platform-Specific Notes

macOS Build Environment

Unicode Character Issues

When building on macOS, you may encounter Unicode-related issues in binary files:

  • Symptom: 0xC3 0xBF (C3BF) patterns in factory.bin
  • Cause: macOS Unicode locale settings
  • Affects: Binary padding operations
Solution

Set C locale in terminal:

# Required environment variables
export LANG=
export LC_COLLATE="C"
export LC_CTYPE="C"
export LC_MESSAGES="C"
export LC_MONETARY="C"
export LC_NUMERIC="C"
export LC_TIME="C"
export LC_ALL=

Workflow:

  1. Set environment variables
  2. Run make commands normally
  3. Verify binary output

For more platform-specific details, see: