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
- Create HAL driver in hal/ directory
- Add corresponding linker script
- 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:
- Command line:
make WOLFBOOT_SECTOR_SIZE=0x1000 WOLFBOOT_PARTITION_SIZE=0x20000
- .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
-
Default Mode
- Uses stack for all operations
- No dynamic memory allocation
- Stack usage varies by algorithm
- Predictable at compile time
-
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
-
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
-
Standard External Flash
make EXT_FLASH=1
- Updates and swap in external flash
- Boot partition in internal flash
- Requires HAL extension
-
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
-
HAL Extension
- Implement
ext_flash_*
API - See HAL Documentation
- Handle custom memory access
- Implement
-
Compatibility Notes
- Incompatible with
NVM_FLASH_WRITEONCE
- Use HAL layer for special flash handling
- Consider word size requirements
- Incompatible with
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:
- Define SPI functions
- See examples in hal/spi/
- 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:
- Set environment variables
- Run make commands normally
- Verify binary output
For more platform-specific details, see: