PR cleanups based on peer review. Fixes to support < 10KB wolfBoot for either RSA2048 or ED25519. Partition scheme allows 10KB application partition or (6KB actual due to NVM write once). Made space using NO_MPU=1, RAM_CODE=0, USE_SLOW_SHA256 and !FLASH_SECURABLE_MEMORY_SUPPORT.

pull/381/head
David Garske 2023-10-09 13:05:46 -07:00 committed by Daniele Lacamera
parent a1d584b838
commit c4dfa3f986
9 changed files with 69 additions and 154 deletions

View File

@ -87,11 +87,6 @@ ifeq ($(ARCH),ARM)
ifeq ($(TARGET),stm32c0)
CORTEX_M0=1
ARCH_FLASH_OFFSET=0x08000000
# Enable this feature for secure memory support
# Makes the flash sectors for the bootloader unacessible from the application
# Requires using the STM32CubeProgrammer to set FLASH_SECR -> SEC_SIZE pages
CFLAGS+=-DFLASH_SECURABLE_MEMORY_SUPPORT
endif
ifeq ($(TARGET),stm32g0)
@ -99,7 +94,7 @@ ifeq ($(ARCH),ARM)
ARCH_FLASH_OFFSET=0x08000000
# Enable this feature for secure memory support
# Makes the flash sectors for the bootloader unacessible from the application
# Makes the flash sectors for the bootloader unaccessible from the application
# Requires using the STM32CubeProgrammer to set FLASH_SECR -> SEC_SIZE pages
CFLAGS+=-DFLASH_SECURABLE_MEMORY_SUPPORT
endif

View File

@ -1,12 +1,13 @@
ARCH?=ARM
TARGET?=stm32c0
SIGN?=ED25519
#Using SHA384 with ED25519 saves about 2kB without SHA256 code
HASH?=SHA384
#Supports ED25519/SHA384 or RSA2048/SHA256
SIGN?=RSA2048
HASH?=SHA256
DEBUG?=0
VTOR?=1
CORTEX_M0?=1
NO_ASM?=0
NO_MPU?=1
EXT_FLASH?=0
SPI_FLASH?=0
ALLOW_DOWNGRADE?=0
@ -14,21 +15,33 @@ NVM_FLASH_WRITEONCE?=1
WOLFBOOT_VERSION?=0
V?=0
SPMATH?=1
RAM_CODE?=1
DUALBANK_SWAP?=0
#Max APP size is 4kB
# Enable this to support wolfBoot self-update
RAM_CODE?=0
# Use slightly smaller SHA2-256
CFLAGS_EXTRA+=-DUSE_SLOW_SHA256
# Enable this feature for secure memory support
# Makes the flash sectors for the bootloader unaccessible from the application
# Requires using the STM32CubeProgrammer to set FLASH_SECR -> SEC_SIZE pages
#CFLAGS_EXTRA+=-DFLASH_SECURABLE_MEMORY_SUPPORT
#Partition: Boot: 10KB, App, 10KB
WOLFBOOT_PARTITION_SIZE?=0x2000
WOLFBOOT_SECTOR_SIZE?=0x800
#Max WOLFBOOT size is 14kB. Currently only 10kB
WOLFBOOT_PARTITION_BOOT_ADDRESS?=0x08003800
WOLFBOOT_PARTITION_UPDATE_ADDRESS?=0x08005800
#Max WOLFBOOT size is 10KB
WOLFBOOT_PARTITION_BOOT_ADDRESS?=0x08002800
WOLFBOOT_PARTITION_UPDATE_ADDRESS?=0x08005000
WOLFBOOT_PARTITION_SWAP_ADDRESS?=0x08007800
#For a debug/not size optimized layout:
#Example debugging partition for larger wolfBoot
#Partition: Boot: 22KB, App, 4K
#DEBUG?=1
#WOLFBOOT_PARTITION_SIZE?=0x1000
#WOLFBOOT_SECTOR_SIZE?=0x800
#WOLFBOOT_PARTITION_BOOT_ADDRESS?=0x08005800
#WOLFBOOT_PARTITION_UPDATE_ADDRESS?=0x08006800
#WOLFBOOT_PARTITION_SWAP_ADDRESS?=0x08007800

View File

@ -8,18 +8,18 @@ and the application initiating the firmware upgrade through the application libr
ensuring that the MCU is running at full speed during boot (to optimize the
verification of the signatures).
The implementation of the hardware-specific calls for each platform are grouped in
The implementation of the hardware-specific calls for each platform are grouped in
a single c file in the [hal](../hal) directory.
The directory also contains a platform-specific linker script for each supported MCU,
with the same name and the `.ld` extension. This is used to link the bootloader's
firmware on the specific hardware, exporting all the necessary symbols for flash
The directory also contains a platform-specific linker script for each supported MCU,
with the same name and the `.ld` extension. This is used to link the bootloader's
firmware on the specific hardware, exporting all the necessary symbols for flash
and RAM boundaries.
## Supported platforms
The following platforms are supported in the current version:
- STM32F4, STM32L5, STM32L0, STM32F7, STM32H7, STM32G0, STM32C0
- STM32C0, STM32F4, STM32F7, STM32G0, STM32H7, STM32L5, STM32L0, STM32U5, STM32WB55
- nRF52
- Atmel samR21
- TI cc26x2
@ -34,8 +34,8 @@ be implemented for each supported target:
`void hal_init(void)`
This function is called by the bootloader at the very beginning of the execution.
Ideally, the implementation provided configures the clock settings for the target
microcontroller, to ensure that it runs at at the required speed to shorten the
Ideally, the implementation provided configures the clock settings for the target
microcontroller, to ensure that it runs at at the required speed to shorten the
time required for the cryptography primitives to verify the firmware images.
`void hal_flash_unlock(void)`
@ -76,11 +76,11 @@ that the state of the microcontroller is restored to its original settings.
WolfBoot can be compiled with the makefile option `EXT_FLASH=1`. When the external flash support is
enabled, update and swap partitions can be associated to an external memory, and will use alternative
HAL function for read/write/erase access.
To associate the update or the swap partition to an external memory, define `PART_UPDATE_EXT` and/or
HAL function for read/write/erase access.
To associate the update or the swap partition to an external memory, define `PART_UPDATE_EXT` and/or
`PART_SWAP_EXT`, respectively.
The following functions are used to access the external memory, and must be defined when `EXT\_FLASH`
The following functions are used to access the external memory, and must be defined when `EXT\_FLASH`
is on:
`int ext_flash_write(uintptr_t address, const uint8_t *data, int len)`
@ -96,15 +96,15 @@ or a negative value in case of failure.
This function provides an indirect read of the external memory, using the
driver's specific interface. `address` is the offset from the beginning of the
addressable space in the device, `data` is a pointer where payload is stored upon a successful
call, and `len` is the maximum size allowed for the payload. `ext_flash_read` should return 0
call, and `len` is the maximum size allowed for the payload. `ext_flash_read` should return 0
upon success, or a negative value in case of failure.
`int ext_flash_erase(uintptr_t address, int len)`
Called by the bootloader to erase part of the external memory.
Erase operations must be performed via the specific interface of the target driver (e.g. SPI flash).
`address` marks the start of the area relative to the device, that the bootloader wants to erase,
and `len` specifies the size of the area to be erased. This function must take into account the
`address` marks the start of the area relative to the device, that the bootloader wants to erase,
and `len` specifies the size of the area to be erased. This function must take into account the
geometry of the sectors, and erase all the sectors in between.
`void ext_flash_lock(void)`

View File

@ -427,50 +427,46 @@ mon reset init
## STM32C0
Supports STM32C0x0/STM32C0x1.
Supports STM32C0x0/STM32C0x1. Instructions are for the STM Nucleo-C031C6 dev board.
Example and instructions are for the STM Nucleo-C031C6 dev board using the
STM32Cube
Tested build configurations:
* With RSA2048 and SHA2-256 the code size is 9724 and it boots in under 1 second.
* With ED25519 and SHA2-384 the code size is 10024 and takes about 10 seconds for the LED to turn on.
Example 32KB partitioning on STM32-G070:
- Sector size: 2KB
- Wolfboot partition size: 14KB
- Application partition size: 8 KB
- Wolfboot partition size: 10KB
- Application partition size: 10 KB
- Swap size 2KB
```C
#define WOLFBOOT_SECTOR_SIZE 0x800 /* 2 KB */
#define WOLFBOOT_PARTITION_BOOT_ADDRESS 0x08004000 /* offset 16kB to 24kB */
#define WOLFBOOT_PARTITION_SIZE 0x2000 /* 8 KB */
#define WOLFBOOT_PARTITION_UPDATE_ADDRESS 0x08006000 /* offset 24kB to 32kB */
#define WOLFBOOT_PARTITION_SWAP_ADDRESS 0x08003800 /* offset 14kB to 16kB */
#define WOLFBOOT_PARTITION_BOOT_ADDRESS 0x08002800 /* at 10KB */
#define WOLFBOOT_PARTITION_SIZE 0x2800 /* 10 KB */
#define WOLFBOOT_PARTITION_UPDATE_ADDRESS 0x08005000 /* at 20KB */
#define WOLFBOOT_PARTITION_SWAP_ADDRESS 0x08007800 /* at 30KB */
```
### Building STM32C0
xxx
Reference configuration (see [/config/examples/stm32g0.config](/config/examples/stm32g0.config)).
You can copy this to wolfBoot root as `.config`: `cp ./config/examples/stm32g0.config .config`.
Reference configuration (see [/config/examples/stm32c0.config](/config/examples/stm32c0.config)).
You can copy this to wolfBoot root as `.config`: `cp ./config/examples/stm32c0.config .config`.
To build you can use `make`.
The TARGET for this is `stm32g0`: `make TARGET=stm32g0`.
The TARGET for this is `stm32c0`: `make TARGET=stm32c0`.
The option `CORTEX_M0` is automatically selected for this target.
The option `NVM_FLASH_WRITEONCE=1` is mandatory on this target, since the IAP driver does not support
multiple writes after each erase operation.
This target also supports secure memory protection on the bootloader region
using the `FLASH_CR:SEC_PROT` and `FLASH_SECT:SEC_SIZE` registers. This is the
number of 2KB pages to block access to from the 0x8000000 base address.
```
STM32_Programmer_CLI -c port=swd mode=hotplug -ob SEC_SIZE=0x10
```
For RAMFUNCTION support (required for SEC_PROT) make sure `RAM_CODE=1`.
### STM32C0 Programming
xxx
Compile requirements: `make TARGET=stm32g0 NVM_FLASH_WRITEONCE=1`
Compile requirements: `make TARGET=stm32c0 NVM_FLASH_WRITEONCE=1`
The output is a single `factory.bin` that includes `wolfboot.bin` and `test-app/image_v1_signed.bin` combined together.
This should be programmed to the flash start address `0x08000000`.
@ -482,7 +478,7 @@ STM32_Programmer_CLI -c port=swd -d factory.bin 0x08000000
```
### STM32C0 Debugging
xxx
Use `make DEBUG=1` and program firmware again.
Start GDB server on port 3333:

View File

@ -26,9 +26,6 @@
# error "wolfBoot STM32C0 HAL: no WRITEONCE support detected. Please define NVM_FLASH_WRITEONCE"
#endif
/* XXX Debug only! */
#define NO_FLASH_SEC_SIZE_CHECK 1
/* STM32 C0 register configuration */
/* Assembly helpers */
@ -138,8 +135,6 @@ static void RAMFUNCTION flash_clear_errors(void)
{
/* Consider only writing here as there is no reason to read first (rc_w1),
* unless other error bits are set*/
/* FLASH_SR = (FLASH_SR_SIZERR | FLASH_SR_PGAERR | FLASH_SR_WRPERR |
FLASH_SR_PROGERR); */
FLASH_SR |= (FLASH_SR_SIZERR | FLASH_SR_PGAERR | FLASH_SR_WRPERR |
FLASH_SR_PROGERR);
}
@ -233,17 +228,11 @@ static void clock_pll_off(void)
reg32 &= ~((1 << 1) | (1 << 0));
RCC_CFGR = (reg32 | RCC_CFGR_SW_HSISYS);
DMB();
#if 0
/* Turn off PLL */
RCC_CR &= ~RCC_CR_PLLON;
DMB();
#endif
}
/* This implementation will setup HSI RC 48 MHz as System Clock Source, set
* flash wait state to 2, and set all peripherals to 16MHz (div4)
*
* */
* flash wait state to 1, and set all peripherals to 16MHz (div4)
*/
static void clock_pll_on(int powersave)
{
uint32_t reg32;
@ -276,45 +265,6 @@ static void clock_pll_on(int powersave)
RCC_CFGR = (reg32 | RCC_CFGR_SW_HSISYS);
DMB();
#if 0
/* Disable PLL */
RCC_CR &= ~RCC_CR_PLLON;
/* Set prescalers for AHB, ADC, ABP1, ABP2. */
reg32 = RCC_CFGR;
reg32 &= ~(0xF0); /* don't change bits [0-3] that were previously set */
RCC_CFGR = (reg32 | (hpre << 8)); /* RM0444 - 5.4.3 - RCC_CFGR */
DMB();
reg32 = RCC_CFGR;
reg32 &= ~(0x1C00); /* don't change bits [0-14] */
RCC_CFGR = (reg32 | (ppre << 12)); /* RM0444 - 5.4.3 - RCC_CFGR */
DMB();
/* Set PLL config */
reg32 = RCC_PLLCFGR;
reg32 |= RCC_PLLCFGR_PLLSRC_HSI16;
reg32 |= ((pllm - 1) << 4);
reg32 |= plln << 8;
reg32 |= ((pllp - 1) << 17);
reg32 |= ((pllr - 1) << 29);
RCC_PLLCFGR = reg32;
DMB();
/* Enable PLL oscillator and wait for it to stabilize. */
RCC_PLLCFGR |= RCC_PLLCFGR_PLLR_EN;
RCC_CR |= RCC_CR_PLLON;
DMB();
while ((RCC_CR & RCC_CR_PLLRDY) == 0) {};
/* Select PLL as SYSCLK source. */
reg32 = RCC_CFGR;
reg32 &= ~((1 << 1) | (1 << 0));
RCC_CFGR = (reg32 | RCC_CFGR_SW_PLL);
DMB();
/* Wait for PLL clock to be selected. */
while ((RCC_CFGR & ((1 << 1) | (1 << 0))) != RCC_CFGR_SW_PLL) {};
#endif
/* SYSCFG, COMP and VREFBUF clock enable */
APB2_CLOCK_ER |= SYSCFG_APB2_CLOCK_ER_VAL;
}

View File

@ -1,7 +1,7 @@
MEMORY
{
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = @BOOTLOADER_PARTITION_SIZE@
RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00002FFF
RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 12K-1
}
SECTIONS

View File

@ -267,6 +267,9 @@ endif
ifeq ($(TARGET),stm32g0)
CFLAGS+=-DNVM_FLASH_WRITEONCE=1
endif
ifeq ($(TARGET),stm32c0)
CFLAGS+=-DNVM_FLASH_WRITEONCE=1
endif
ifeq ($(TARGET),hifive1.freedom)
CFLAGS+=-I$(FREEDOM_E_SDK)/freedom-metal/ -D__METAL_MACHINE_HEADER=\"$(FREEDOM_E_SDK)/bsp/sifive-hifive1/metal.h\"

View File

@ -1,4 +1,4 @@
/* main.c
/* app_stm32c0.c
*
* Test bare-metal boot-led-on application
*
@ -36,4 +36,3 @@ void main(void) {
;
}
#endif /* PLATFORM_stm32c0 */

View File

@ -110,13 +110,9 @@ void boot_led_off(void)
#endif /* PLATFORM_stm32l0 */
#ifdef PLATFORM_stm32g0
#include <stdint.h>
#include "wolfboot/wolfboot.h"
/*GPIOA5*/
#define RCC_IOPENR (*(volatile uint32_t *)(0x40021034)) // 40021034
#if defined(PLATFORM_stm32g0) || defined(PLATFORM_stm32c0)
/* GPIOA5 */
#define RCC_IOPENR (*(volatile uint32_t *)(0x40021034))
#define RCC_IOPENR_GPIOAEN (1 << 0)
#define GPIOA_BASE 0x50000000
@ -138,50 +134,13 @@ void boot_led_on(void)
uint32_t pin = LED_BOOT_PIN;
RCC_IOPENR |= RCC_IOPENR_GPIOAEN;
reg = GPIOA_MODE & ~(0x03 << (pin * 2));
GPIOA_MODE = reg | (1 << (pin * 2)); // general purpose output mode
GPIOA_MODE = reg | (1 << (pin * 2)); /* general purpose output mode */
reg = GPIOA_PUPD & ~(0x03 << (pin * 2));
GPIOA_PUPD = reg | (1 << (pin * 2)); // pull-up
GPIOA_BSRR |= (1 << pin); // set pin
GPIOA_PUPD = reg | (1 << (pin * 2)); /* pull-up */
GPIOA_BSRR |= (1 << pin); /* set pin */
}
#endif /** PLATFORM_stm32g0 **/
#ifdef PLATFORM_stm32c0
#include <stdint.h>
#include "wolfboot/wolfboot.h"
/*GPIOA5 on Nucleo C031C6*/
#define RCC_IOPENR (*(volatile uint32_t *)(0x40021034)) // 40021034
#define RCC_IOPENR_GPIOAEN (1 << 0)
#define GPIOA_BASE 0x50000000
#define GPIOA_MODE (*(volatile uint32_t *)(GPIOA_BASE + 0x00))
#define GPIOA_OTYPE (*(volatile uint32_t *)(GPIOA_BASE + 0x04))
#define GPIOA_OSPD (*(volatile uint32_t *)(GPIOA_BASE + 0x08))
#define GPIOA_PUPD (*(volatile uint32_t *)(GPIOA_BASE + 0x0c))
#define GPIOA_ODR (*(volatile uint32_t *)(GPIOA_BASE + 0x14))
#define GPIOA_BSRR (*(volatile uint32_t *)(GPIOA_BASE + 0x18))
#define GPIOA_AFL (*(volatile uint32_t *)(GPIOA_BASE + 0x20))
#define GPIOA_AFH (*(volatile uint32_t *)(GPIOA_BASE + 0x24))
#define LED_PIN (5)
#define LED_BOOT_PIN (5)
#define GPIO_OSPEED_100MHZ (0x03)
void boot_led_on(void)
{
uint32_t reg;
uint32_t pin = LED_BOOT_PIN;
RCC_IOPENR |= RCC_IOPENR_GPIOAEN;
reg = GPIOA_MODE & ~(0x03 << (pin * 2));
GPIOA_MODE = reg | (1 << (pin * 2)); // general purpose output mode
reg = GPIOA_PUPD & ~(0x03 << (pin * 2));
GPIOA_PUPD = reg | (1 << (pin * 2)); // pull-up
GPIOA_BSRR |= (1 << pin); // set pin
}
#endif /** PLATFORM_stm32c0 **/
#endif /* PLATFORM_stm32g0 || PLATFORM_stm32c0 */
#ifdef PLATFORM_stm32wb
#define LED_BOOT_PIN (0)