diff --git a/.github/workflows/test-configs.yml b/.github/workflows/test-configs.yml index 11159bf3c2..1d816d65d6 100644 --- a/.github/workflows/test-configs.yml +++ b/.github/workflows/test-configs.yml @@ -604,6 +604,12 @@ jobs: arch: arm config-file: ./config/examples/stm32wb.config + wolfhal_stm32wb_test: + uses: ./.github/workflows/test-build.yml + with: + arch: arm + config-file: ./config/examples/wolfhal_stm32wb_nucleo.config + # TODO: ti-tms570lc435.config requires F021 Flash API (Windows installer only) # ti_tms570lc435_test: # uses: ./.github/workflows/test-build-ti-hercules.yml diff --git a/.gitmodules b/.gitmodules index 6cd81662fe..13396fd2ec 100644 --- a/.gitmodules +++ b/.gitmodules @@ -13,3 +13,6 @@ [submodule "lib/wolfPSA"] path = lib/wolfPSA url = https://github.com/wolfSSL/wolfPSA.git +[submodule "lib/wolfHAL"] + path = lib/wolfHAL + url = https://github.com/wolfSSL/wolfHAL.git diff --git a/Makefile b/Makefile index 0acddd3252..d78cdac670 100644 --- a/Makefile +++ b/Makefile @@ -170,6 +170,14 @@ export WOLFBOOT_LIB_WOLFHSM ## Architecture/CPU configuration include arch.mk +ifeq ($(TARGET),wolfhal) + ifeq ($(strip $(BOARD)),) + $(error TARGET=wolfhal requires BOARD to be set, e.g. BOARD=stm32wb_nucleo) + endif + OBJS+=./hal/boards/$(BOARD)/board.o + include hal/boards/$(BOARD)/board.mk +endif + # Parse config options include options.mk @@ -534,7 +542,10 @@ $(LSCRIPT): $(LSCRIPT_IN) FORCE sed -e "s/@IMAGE_HEADER_SIZE@/$(IMAGE_HEADER_SIZE)/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" \ + sed -e "s/@L2SRAM_ADDR@/$(L2SRAM_ADDR)/g" | \ + sed -e 's/@WOLFHAL_FLASH_EXCLUDE_TEXT@/$(WOLFHAL_FLASH_EXCLUDE_TEXT)/g' | \ + sed -e 's/@WOLFHAL_FLASH_EXCLUDE_RODATA@/$(WOLFHAL_FLASH_EXCLUDE_RODATA)/g' | \ + sed -e 's/@WOLFHAL_FLASH_RAM_SECTIONS@/$(WOLFHAL_FLASH_RAM_SECTIONS)/g' \ > $@ hex: wolfboot.hex diff --git a/arch.mk b/arch.mk index 74663afa57..375d1780bf 100644 --- a/arch.mk +++ b/arch.mk @@ -214,6 +214,11 @@ ifeq ($(ARCH),ARM) SPI_TARGET=stm32 endif + # Defaults for linker script placeholders (overridden by wolfhal target) + WOLFHAL_FLASH_EXCLUDE_TEXT?=*(.text*) + WOLFHAL_FLASH_EXCLUDE_RODATA?=*(.rodata*) + WOLFHAL_FLASH_RAM_SECTIONS?= + ifeq ($(TARGET),stm32wb) ARCH_FLASH_OFFSET=0x08000000 SPI_TARGET=stm32 @@ -229,6 +234,10 @@ ifeq ($(ARCH),ARM) endif endif + ifeq ($(TARGET),wolfhal) + WOLFHAL_ROOT?=$(WOLFBOOT_ROOT)/lib/wolfHAL + CFLAGS+=-I$(WOLFHAL_ROOT) -DWHAL_CFG_NO_TIMEOUT -Ihal/boards/$(BOARD) + endif ifeq ($(TARGET),stm32l5) CORTEX_M33=1 diff --git a/config/examples/wolfhal_stm32wb_nucleo.config b/config/examples/wolfhal_stm32wb_nucleo.config new file mode 100644 index 0000000000..2d023b063a --- /dev/null +++ b/config/examples/wolfhal_stm32wb_nucleo.config @@ -0,0 +1,10 @@ +TARGET=wolfhal +BOARD=stm32wb_nucleo +SIGN=ECC256 +HASH=SHA256 +WOLFBOOT_SECTOR_SIZE=0x1000 +WOLFBOOT_PARTITION_SIZE=0x20000 +WOLFBOOT_PARTITION_BOOT_ADDRESS=0x08008000 +WOLFBOOT_PARTITION_UPDATE_ADDRESS=0x08028000 +WOLFBOOT_PARTITION_SWAP_ADDRESS=0x08048000 +NVM_FLASH_WRITEONCE=1 diff --git a/docs/wolfHAL.md b/docs/wolfHAL.md new file mode 100644 index 0000000000..223c671ec9 --- /dev/null +++ b/docs/wolfHAL.md @@ -0,0 +1,247 @@ +# wolfHAL Integration + +wolfBoot supports [wolfHAL](https://github.com/wolfSSL/wolfHAL) as an alternative +hardware abstraction layer backend. wolfHAL provides portable drivers for common MCU +peripherals (clock, flash, GPIO, UART, SPI, etc.) with a consistent API across +platforms. + +## Overview + +The wolfHAL integration uses a single generic `TARGET=wolfhal` with a per-board +abstraction layer. All board-specific details — device instances, driver bindings, +build flags, and linker scripts — live in a self-contained board directory. Adding +support for a new board or MCU family requires no changes to the core build system or +HAL shim. + +The integration consists of four parts: + +1. **Generic HAL shim** (`hal/wolfhal.c`) — implements the wolfBoot HAL API + (`hal_flash_write`, `hal_flash_erase`, etc.) by calling `Board_*` macros. This + file is shared across all wolfHAL boards. + +2. **Board directory** (`hal/boards//`) — contains three files that fully + describe a board: + - `board.h` — `#define` macros mapping generic `Board_*` APIs to chip-specific + wolfHAL driver functions. + - `board.c` — device instances (clock, flash, GPIO, UART), configuration + structs, and `hal_init`/`hal_prepare_boot` implementations. + - `board.mk` — build variables (`ARCH_FLASH_OFFSET`, `LSCRIPT_IN`, wolfHAL + driver objects, `RAM_CODE` linker rules). + +3. **Generic test application** (`test-app/app_wolfhal.c`) — demonstrates using + wolfHAL peripherals (GPIO, UART) beyond what the bootloader needs, using the same + `Board_*` API. + +4. **wolfHAL library** (`lib/wolfHAL/`) — the wolfHAL submodule containing the + platform drivers. + +### How It Fits Together + +``` +config/examples/wolfhal_.config + └─ TARGET=wolfhal BOARD= + +arch.mk + └─ Sets WOLFHAL_ROOT, CFLAGS += -Ihal/boards/$(BOARD) + +Makefile + └─ OBJS += hal/boards/$(BOARD)/board.o + └─ include hal/boards/$(BOARD)/board.mk + +hal/wolfhal.c (generic — calls Board_Flash_Write, Board_Uart_Send, etc.) + └─ #include "board.h" (resolved via -I to the board directory) + +hal/boards// + ├─ board.h (#define Board_Flash_Write → whal_Flash_Write) + ├─ board.c (device instances, hal_init, hal_prepare_boot) + └─ board.mk (ARCH_FLASH_OFFSET, LSCRIPT_IN, driver objects, RAM_CODE rules) +``` + +The `board.h` macros resolve `Board_*` calls directly to the chip-specific wolfHAL +driver functions at compile time. This avoids vtable indirection and allows the +linker to garbage-collect unused driver code (with `-Wl,--gc-sections`). + +## Configuration + +A wolfHAL-based config requires two variables beyond the standard wolfBoot settings: + +``` +TARGET=wolfhal +BOARD=stm32wb_nucleo +``` + +- `TARGET=wolfhal` selects the generic wolfHAL HAL shim and build path. +- `BOARD` selects the board directory under `hal/boards/`. + +See `config/examples/wolfhal_*.config` for complete examples. + +## Adding a New Board + +To add a new board, create a directory `hal/boards//` with three files: + +### 1. `board.h` — API Mappings + +Map each generic `Board_*` macro to the appropriate wolfHAL driver function for your +MCU family. The required mappings are: + +```c +#ifndef WOLFHAL_BOARD_H +#define WOLFHAL_BOARD_H + +#include _clock.h> +#include _flash.h> +#include _gpio.h> +#include _uart.h> + +/* Clock */ +#define Board_Clock_Init whal_Clock_Init +#define Board_Clock_Deinit whal_Clock_Deinit +#define Board_Clock_Enable whal_Clock_Enable +#define Board_Clock_Disable whal_Clock_Disable + +/* Flash */ +#define Board_Flash_Init whal_Flash_Init +#define Board_Flash_Deinit whal_Flash_Deinit +#define Board_Flash_Lock whal_Flash_Lock +#define Board_Flash_Unlock whal_Flash_Unlock +#define Board_Flash_Write whal_Flash_Write +#define Board_Flash_Erase whal_Flash_Erase + +/* GPIO */ +#define Board_Gpio_Init whal_Gpio_Init +#define Board_Gpio_Deinit whal_Gpio_Deinit +#define Board_Gpio_Set whal_Gpio_Set +#define Board_Gpio_Get whal_Gpio_Get + +/* UART */ +#define Board_Uart_Init whal_Uart_Init +#define Board_Uart_Deinit whal_Uart_Deinit +#define Board_Uart_Send whal_Uart_Send +#define Board_Uart_Recv whal_Uart_Recv + +#endif /* WOLFHAL_BOARD_H */ +``` + +### 2. `board.c` — Device Instances and Initialization + +Define the wolfHAL device instances and implement `hal_init` and `hal_prepare_boot`. +The file must export `g_wbFlash` (and `g_wbUart` when `DEBUG_UART` is enabled) as +non-static globals — these are referenced by `hal/wolfhal.c` via `extern`. + +```c +#include "hal.h" +#include "board.h" + +/* Clock controller */ +whal_Clock g_wbClock = { + .regmap = { .base = ..., .size = 0x400 }, + .cfg = &(_clock_cfg) { ... }, +}; + +/* Flash */ +whal_Flash g_wbFlash = { + .regmap = { .base = ..., .size = 0x400 }, + .cfg = &(_flash_cfg) { + .startAddr = 0x08000000, + .size = ..., + }, +}; + +#ifdef DEBUG_UART +whal_Gpio g_wbGpio = { ... }; +whal_Uart g_wbUart = { ... }; +#endif + +void hal_init(void) +{ + /* Initialize clock tree, flash, and optionally GPIO/UART */ + Board_Clock_Init(&g_wbClock); + Board_Flash_Init(&g_wbFlash); +#ifdef DEBUG_UART + Board_Gpio_Init(&g_wbGpio); + Board_Uart_Init(&g_wbUart); +#endif +} + +void hal_prepare_boot(void) +{ +#ifdef DEBUG_UART + Board_Uart_Deinit(&g_wbUart); + Board_Gpio_Deinit(&g_wbGpio); +#endif + Board_Flash_Deinit(&g_wbFlash); + Board_Clock_Deinit(&g_wbClock); +} +``` + +### 3. `board.mk` — Build Variables + +Provide the build-time configuration: flash offset, linker script, and the wolfHAL +driver objects needed for your MCU family. + +```makefile +ARCH_FLASH_OFFSET=0x08000000 +LSCRIPT_IN=hal/.ld + +WOLFHAL_OBJS+=$(WOLFHAL_ROOT)/src/clock/_clock.o +WOLFHAL_OBJS+=$(WOLFHAL_ROOT)/src/flash/_flash.o +ifeq ($(DEBUG_UART),1) + WOLFHAL_OBJS+=$(WOLFHAL_ROOT)/src/gpio/_gpio.o + WOLFHAL_OBJS+=$(WOLFHAL_ROOT)/src/uart/_uart.o +endif + +OBJS+=$(WOLFHAL_OBJS) +APP_OBJS+=$(WOLFHAL_OBJS) + +ifeq ($(RAM_CODE),1) + WOLFHAL_FLASH_EXCLUDE_TEXT=*(EXCLUDE_FILE(*_flash.o) .text*) + WOLFHAL_FLASH_EXCLUDE_RODATA=*(EXCLUDE_FILE(*_flash.o) .rodata*) + WOLFHAL_FLASH_RAM_SECTIONS=*_flash.o(.text* .rodata*) +endif +``` + +### 4. Config File + +Create `config/examples/wolfhal_.config`: + +``` +TARGET=wolfhal +BOARD= +SIGN=ECC256 +HASH=SHA256 +WOLFBOOT_SECTOR_SIZE=0x1000 +WOLFBOOT_PARTITION_SIZE=0x20000 +WOLFBOOT_PARTITION_BOOT_ADDRESS=0x08008000 +WOLFBOOT_PARTITION_UPDATE_ADDRESS=0x08028000 +WOLFBOOT_PARTITION_SWAP_ADDRESS=0x08048000 +NVM_FLASH_WRITEONCE=1 +``` + +Adjust partition addresses and sector sizes for your board's flash layout. Optionally +add `DEBUG_UART=1` to enable UART debug output. + +## RAM_CODE + +When `RAM_CODE=1` is set, wolfBoot's core flash update functions are placed in RAM +via the `RAMFUNCTION` attribute. For wolfHAL boards, the `board.mk` defines +`EXCLUDE_FILE` rules that also place the wolfHAL flash driver into RAM. This ensures +all flash operations execute from RAM, which is required on MCUs that stall or fault +when code executes from the same flash bank being programmed. + +The linker script uses `@WOLFHAL_FLASH_EXCLUDE_TEXT@`, +`@WOLFHAL_FLASH_EXCLUDE_RODATA@`, and `@WOLFHAL_FLASH_RAM_SECTIONS@` placeholders +that are substituted at build time. When `RAM_CODE=1`, these expand to +`EXCLUDE_FILE` rules that move the flash driver's `.text` and `.rodata` sections from +flash into the `.data` section (loaded to RAM at startup). When `RAM_CODE` is not +set, all code remains in flash as normal. + +## Test Application + +The generic test application (`test-app/app_wolfhal.c`) demonstrates using wolfHAL +peripherals beyond what the bootloader needs. It accesses the board-provided GPIO and +UART instances (`g_wbGpio`, `g_wbUart`) via `extern`, using the `Board_*` API to +toggle an LED and send serial output, then exercises the wolfBoot update mechanism. + +The test-app Makefile compiles its own copy of the board file (`board_.o`) +with `DEBUG_UART=1` always defined, since the app needs UART and GPIO regardless of +the bootloader's `DEBUG_UART` setting. diff --git a/hal/boards/stm32wb_nucleo/board.c b/hal/boards/stm32wb_nucleo/board.c new file mode 100644 index 0000000000..084ff225bc --- /dev/null +++ b/hal/boards/stm32wb_nucleo/board.c @@ -0,0 +1,136 @@ +/* board.c + * + * wolfHAL board configuration for the STM32WB55 Nucleo + * + * Copyright (C) 2026 wolfSSL Inc. + * + * This file is part of wolfBoot. + * + * wolfBoot is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * wolfBoot is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +#include "hal.h" +#include "board.h" +#include + +/* Clock */ +whal_Clock g_wbClock = { + .regmap = { .base = 0x58000000, .size = 0x400 }, + + .cfg = &(whal_Stm32wbRcc_Cfg) { + .sysClkSrc = WHAL_STM32WB_RCC_SYSCLK_SRC_PLL, + .sysClkCfg = &(whal_Stm32wbRcc_PllClkCfg) { + .clkSrc = WHAL_STM32WB_RCC_PLLCLK_SRC_MSI, + /* 64 MHz: (4 MHz MSI / 1) * 32 / 2 = 64 MHz */ + .n = 32, + .m = 0, + .r = 1, + .q = 0, + .p = 0, + }, + }, +}; + +static const whal_Stm32wbRcc_Clk flashClk = {WHAL_STM32WB55_FLASH_CLOCK}; + +/* Flash */ +whal_Flash g_wbFlash = { + .regmap = { .base = 0x58004000, .size = 0x400 }, + + .cfg = &(whal_Stm32wbFlash_Cfg) { + .startAddr = 0x08000000, + .size = 0x100000, + }, +}; + +#ifdef DEBUG_UART + +static const whal_Stm32wbRcc_Clk g_clocks[] = { + {WHAL_STM32WB55_GPIOB_CLOCK}, + {WHAL_STM32WB55_UART1_CLOCK}, +}; +#define CLOCK_COUNT (sizeof(g_clocks) / sizeof(g_clocks[0])) + +/* GPIO — LED on PB5, UART1 TX/RX on PB6/PB7 */ +whal_Gpio g_wbGpio = { + .regmap = { .base = 0x48000000, .size = 0x400 }, + + .cfg = &(whal_Stm32wbGpio_Cfg) { + .pinCfg = (whal_Stm32wbGpio_PinCfg[]) { + [BOARD_LED_PIN] = WHAL_STM32WB_GPIO_PIN( + WHAL_STM32WB_GPIO_PORT_B, 5, WHAL_STM32WB_GPIO_MODE_OUT, + WHAL_STM32WB_GPIO_OUTTYPE_PUSHPULL, WHAL_STM32WB_GPIO_SPEED_LOW, + WHAL_STM32WB_GPIO_PULL_UP, 0), + [BOARD_UART_TX_PIN] = WHAL_STM32WB_GPIO_PIN( + WHAL_STM32WB_GPIO_PORT_B, 6, WHAL_STM32WB_GPIO_MODE_ALTFN, + WHAL_STM32WB_GPIO_OUTTYPE_PUSHPULL, WHAL_STM32WB_GPIO_SPEED_FAST, + WHAL_STM32WB_GPIO_PULL_UP, 7), + [BOARD_UART_RX_PIN] = WHAL_STM32WB_GPIO_PIN( + WHAL_STM32WB_GPIO_PORT_B, 7, WHAL_STM32WB_GPIO_MODE_ALTFN, + WHAL_STM32WB_GPIO_OUTTYPE_PUSHPULL, WHAL_STM32WB_GPIO_SPEED_FAST, + WHAL_STM32WB_GPIO_PULL_UP, 7), + }, + .pinCount = BOARD_PIN_COUNT, + }, +}; + +/* UART1 at 115200 baud */ +whal_Uart g_wbUart = { + .regmap = { .base = 0x40013800, .size = 0x400 }, + + .cfg = &(whal_Stm32wbUart_Cfg) { + .brr = WHAL_STM32WB_UART_BRR(64000000, 115200), + }, +}; + +#endif /* DEBUG_UART */ + +void hal_init(void) +{ + /* Enable flash clock and set latency before increasing clock speed */ + whal_Stm32wbRcc_Enable(&g_wbClock, &flashClk); + whal_Stm32wbFlash_Ext_SetLatency(&g_wbFlash, WHAL_STM32WB_FLASH_LATENCY_3); + + whal_Stm32wbRccPll_Init(&g_wbClock); + whal_Stm32wbFlash_Init(&g_wbFlash); + +#ifdef DEBUG_UART + for (size_t i = 0; i < CLOCK_COUNT; i++) { + whal_Stm32wbRcc_Enable(&g_wbClock, &g_clocks[i]); + } + + whal_Stm32wbGpio_Init(&g_wbGpio); + whal_Stm32wbUart_Init(&g_wbUart); +#endif +} + +void hal_prepare_boot(void) +{ +#ifdef DEBUG_UART + whal_Stm32wbUart_Deinit(&g_wbUart); + whal_Stm32wbGpio_Deinit(&g_wbGpio); + + for (size_t i = 0; i < CLOCK_COUNT; i++) { + whal_Stm32wbRcc_Disable(&g_wbClock, &g_clocks[i]); + } +#endif + + whal_Stm32wbFlash_Deinit(&g_wbFlash); + whal_Stm32wbRccPll_Deinit(&g_wbClock); + + /* Reduce flash latency then disable flash clock */ + whal_Stm32wbFlash_Ext_SetLatency(&g_wbFlash, WHAL_STM32WB_FLASH_LATENCY_0); + whal_Stm32wbRcc_Disable(&g_wbClock, &flashClk); +} diff --git a/hal/boards/stm32wb_nucleo/board.h b/hal/boards/stm32wb_nucleo/board.h new file mode 100644 index 0000000000..cb6cb2f70e --- /dev/null +++ b/hal/boards/stm32wb_nucleo/board.h @@ -0,0 +1,70 @@ +/* board.h + * + * Direct API mappings for the STM32WB55 Nucleo board. + * + * These macros bypass vtable dispatch and call the STM32WB driver functions + * directly — eliminating pointer indirection and allowing the linker to GC + * unused driver code. + * + * Copyright (C) 2026 wolfSSL Inc. + * + * This file is part of wolfBoot. + * + * wolfBoot is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * wolfBoot is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +#ifndef WOLFHAL_BOARD_H +#define WOLFHAL_BOARD_H + +#include +#include +#include +#include + +/* GPIO pin indices (matches pin array in board.c) */ +enum { + BOARD_LED_PIN, + BOARD_UART_TX_PIN, + BOARD_UART_RX_PIN, + BOARD_PIN_COUNT, +}; + +/* Clock */ +#define Board_Clock_Init whal_Stm32wbRccPll_Init +#define Board_Clock_Deinit whal_Stm32wbRccPll_Deinit +#define Board_Clock_Enable whal_Stm32wbRcc_Enable +#define Board_Clock_Disable whal_Stm32wbRcc_Disable + +/* Flash */ +#define Board_Flash_Init whal_Stm32wbFlash_Init +#define Board_Flash_Deinit whal_Stm32wbFlash_Deinit +#define Board_Flash_Lock whal_Stm32wbFlash_Lock +#define Board_Flash_Unlock whal_Stm32wbFlash_Unlock +#define Board_Flash_Write whal_Stm32wbFlash_Write +#define Board_Flash_Erase whal_Stm32wbFlash_Erase + +/* GPIO */ +#define Board_Gpio_Init whal_Stm32wbGpio_Init +#define Board_Gpio_Deinit whal_Stm32wbGpio_Deinit +#define Board_Gpio_Set whal_Stm32wbGpio_Set +#define Board_Gpio_Get whal_Stm32wbGpio_Get + +/* UART */ +#define Board_Uart_Init whal_Stm32wbUart_Init +#define Board_Uart_Deinit whal_Stm32wbUart_Deinit +#define Board_Uart_Send whal_Stm32wbUart_Send +#define Board_Uart_Recv whal_Stm32wbUart_Recv + +#endif /* WOLFHAL_BOARD_H */ diff --git a/hal/boards/stm32wb_nucleo/board.mk b/hal/boards/stm32wb_nucleo/board.mk new file mode 100644 index 0000000000..819cf6adee --- /dev/null +++ b/hal/boards/stm32wb_nucleo/board.mk @@ -0,0 +1,18 @@ +ARCH_FLASH_OFFSET=0x08000000 +LSCRIPT_IN=hal/stm32wb.ld + +WOLFHAL_OBJS+=$(WOLFHAL_ROOT)/src/clock/stm32wb_rcc.o +WOLFHAL_OBJS+=$(WOLFHAL_ROOT)/src/flash/stm32wb_flash.o +ifeq ($(DEBUG_UART),1) + WOLFHAL_OBJS+=$(WOLFHAL_ROOT)/src/gpio/stm32wb_gpio.o + WOLFHAL_OBJS+=$(WOLFHAL_ROOT)/src/uart/stm32wb_uart.o +endif + +OBJS+=$(WOLFHAL_OBJS) +APP_OBJS+=$(WOLFHAL_OBJS) + +ifeq ($(RAM_CODE),1) + WOLFHAL_FLASH_EXCLUDE_TEXT=*(EXCLUDE_FILE(*stm32wb_flash.o) .text*) + WOLFHAL_FLASH_EXCLUDE_RODATA=*(EXCLUDE_FILE(*stm32wb_flash.o) .rodata*) + WOLFHAL_FLASH_RAM_SECTIONS=*stm32wb_flash.o(.text* .rodata*) +endif diff --git a/hal/stm32wb.ld b/hal/stm32wb.ld index 14dd5aada4..d7ff658f61 100644 --- a/hal/stm32wb.ld +++ b/hal/stm32wb.ld @@ -10,10 +10,8 @@ SECTIONS { _start_text = .; KEEP(*(.isr_vector)) -; *(EXCLUDE_FILE(*chacha*) .text*) -; *(EXCLUDE_FILE(*chacha*) .rodata*) - *(.text*) - *(.rodata*) + @WOLFHAL_FLASH_EXCLUDE_TEXT@ + @WOLFHAL_FLASH_EXCLUDE_RODATA@ . = ALIGN(4); _end_text = .; } > FLASH @@ -30,9 +28,7 @@ SECTIONS KEEP(*(.data*)) . = ALIGN(4); KEEP(*(.ramcode)) -; KEEP(*(.text.wc_Chacha*)) -; KEEP(*(.rodata.sigma)) -; KEEP(*(.rodata.tau)) + @WOLFHAL_FLASH_RAM_SECTIONS@ . = ALIGN(4); _end_data = .; } > RAM diff --git a/hal/wolfhal.c b/hal/wolfhal.c new file mode 100644 index 0000000000..5396be52c4 --- /dev/null +++ b/hal/wolfhal.c @@ -0,0 +1,60 @@ +/* wolfhal.c + * + * Generic wolfHAL port for wolfBoot. + * + * Copyright (C) 2026 wolfSSL Inc. + * + * This file is part of wolfBoot. + * + * wolfBoot is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * wolfBoot is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +#include +#include "hal.h" +#include "wolfboot/wolfboot.h" +#include "board.h" + +/* Board-provided device instances */ +extern whal_Flash g_wbFlash; +#ifdef DEBUG_UART +extern whal_Uart g_wbUart; +#endif + +void RAMFUNCTION hal_flash_unlock(void) +{ + Board_Flash_Unlock(&g_wbFlash, 0, 0); +} + +void RAMFUNCTION hal_flash_lock(void) +{ + Board_Flash_Lock(&g_wbFlash, 0, 0); +} + +int RAMFUNCTION hal_flash_write(uint32_t address, const uint8_t *data, int len) +{ + return Board_Flash_Write(&g_wbFlash, (size_t)address, data, (size_t)len); +} + +int RAMFUNCTION hal_flash_erase(uint32_t address, int len) +{ + return Board_Flash_Erase(&g_wbFlash, (size_t)address, (size_t)len); +} + +#ifdef DEBUG_UART +void uart_write(const char *buf, unsigned int len) +{ + Board_Uart_Send(&g_wbUart, (const uint8_t *)buf, (size_t)len); +} +#endif diff --git a/lib/wolfHAL b/lib/wolfHAL new file mode 160000 index 0000000000..4757b2fe84 --- /dev/null +++ b/lib/wolfHAL @@ -0,0 +1 @@ +Subproject commit 4757b2fe84a388686677cd0ad28d879f4f079a51 diff --git a/options.mk b/options.mk index ff8df2c4ad..063637b4fe 100644 --- a/options.mk +++ b/options.mk @@ -970,7 +970,9 @@ OBJS+=$(SECURE_OBJS) ifeq ($(RAM_CODE),1) ifeq ($(ENCRYPT),1) ifeq ($(ENCRYPT_WITH_CHACHA),1) - LSCRIPT_IN=hal/$(TARGET)_chacha_ram.ld + ifneq ($(TARGET),wolfhal) + LSCRIPT_IN=hal/$(TARGET)_chacha_ram.ld + endif endif endif ifeq ($(ARCH),ARM) diff --git a/test-app/Makefile b/test-app/Makefile index a2e54effa9..f60001a0da 100644 --- a/test-app/Makefile +++ b/test-app/Makefile @@ -8,6 +8,7 @@ WOLFSSL_LOCAL_OBJDIR?=wolfssl_obj vpath %.c $(WOLFBOOT_LIB_WOLFSSL) vpath %.S $(WOLFBOOT_LIB_WOLFSSL) +WOLFBOOT_ROOT?=.. TARGET?=none ARCH?=ARM MCUXPRESSO_CMSIS?=$(MCUXPRESSO)/CMSIS @@ -62,7 +63,7 @@ ifeq ($(TARGET),ti_hercules) APP_OBJS:=app_$(TARGET).o ../test-app/libwolfboot.o CFLAGS+=-I"../include" else - CFLAGS+=-Wall -ffreestanding -Wno-unused + CFLAGS+=-Wall -ffreestanding -Wno-unused -ffunction-sections -fdata-sections # Stack usage computation not supported on TriCore ifneq ($(ARCH),AURIX_TC3) ifneq ($(USE_CLANG),1) @@ -590,6 +591,16 @@ else ifeq ($(TARGET),stm32wb) APP_OBJS+=../hal/uart/uart_drv_$(UART_TARGET).o endif + ifeq ($(TARGET),wolfhal) + ifeq ($(strip $(BOARD)),) + $(error TARGET=wolfhal requires BOARD to be set, e.g. BOARD=stm32wb_nucleo) + endif + WOLFHAL_ROOT?=$(WOLFBOOT_ROOT)/lib/wolfHAL + CFLAGS+=-I$(WOLFHAL_ROOT) -DWHAL_CFG_NO_TIMEOUT -I$(WOLFBOOT_ROOT)/hal/boards/$(BOARD) + DEBUG_UART=1 + APP_OBJS+=board_$(BOARD).o + include $(WOLFBOOT_ROOT)/hal/boards/$(BOARD)/board.mk + endif endif ifeq ($(TARGET),kinetis) @@ -965,6 +976,10 @@ delta-extra-data: image.bin ../hal/spi/spi_drv_$(SPI_TARGET)_ns.o: ../hal/spi/spi_drv_$(SPI_TARGET).c FORCE $(Q)$(CC) $(CFLAGS) -c -o $(@) ../hal/spi/spi_drv_$(SPI_TARGET).c -DNONSECURE_APP +board_$(BOARD).o: ../hal/boards/$(BOARD)/board.c + @echo "\t[CC-$(ARCH)] $@" + $(Q)$(CC) $(CFLAGS) -DDEBUG_UART -c $(OUTPUT_FLAG) $@ $< + %.o:%.c @echo "\t[CC-$(ARCH)] $@" $(Q)$(CC) $(CFLAGS) -c $(OUTPUT_FLAG) $@ $^ diff --git a/test-app/app_wolfhal.c b/test-app/app_wolfhal.c new file mode 100644 index 0000000000..353544eb3e --- /dev/null +++ b/test-app/app_wolfhal.c @@ -0,0 +1,90 @@ +/* app_wolfhal.c + * + * Generic test bare-metal application using wolfHAL + * + * Copyright (C) 2026 wolfSSL Inc. + * + * This file is part of wolfBoot. + * + * wolfBoot is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * wolfBoot is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +#include +#include +#include +#include "hal.h" +#include "wolfboot/wolfboot.h" +#include "target.h" + +#include "board.h" + +#ifdef TARGET_wolfhal + +/* Board-provided device instances */ +extern whal_Gpio g_wbGpio; +extern whal_Uart g_wbUart; + +/* Matches all keys: + * - chacha (32 + 12) + * - aes128 (16 + 16) + * - aes256 (32 + 16) + */ +char enc_key[] = "0123456789abcdef0123456789abcdef" + "0123456789abcdef"; + +volatile uint32_t time_elapsed = 0; + +void main(void) +{ + uint32_t version; + uint32_t updv; + uint8_t ver_buf[5]; + + hal_init(); + + /* LED on */ + Board_Gpio_Set(&g_wbGpio, BOARD_LED_PIN, 1); + + version = wolfBoot_current_firmware_version(); + updv = wolfBoot_update_firmware_version(); + + ver_buf[0] = '*'; + ver_buf[1] = (version >> 24) & 0xFF; + ver_buf[2] = (version >> 16) & 0xFF; + ver_buf[3] = (version >> 8) & 0xFF; + ver_buf[4] = version & 0xFF; + Board_Uart_Send(&g_wbUart, ver_buf, sizeof(ver_buf)); + + if ((version == 1) && (updv != 8)) { + /* LED off */ + Board_Gpio_Set(&g_wbGpio, BOARD_LED_PIN, 0); +#if EXT_ENCRYPTED + wolfBoot_set_encrypt_key((uint8_t *)enc_key, + (uint8_t *)(enc_key + 32)); +#endif + wolfBoot_update_trigger(); + /* LED on */ + Board_Gpio_Set(&g_wbGpio, BOARD_LED_PIN, 1); + } else { + if (version != 7) + wolfBoot_success(); + } + + /* Wait for reboot */ + while (1) + __asm__ volatile("wfi"); +} + +#endif /* TARGET_wolfhal */