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..8766daf057 --- /dev/null +++ b/docs/wolfHAL.md @@ -0,0 +1,256 @@ +# 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 uses wolfHAL's **direct API mapping** feature. Each platform +driver source provides an optional `#ifdef` block that renames its driver +functions to the top-level API names. When the corresponding +`WHAL_CFG__API_MAPPING_` flag is defined, the driver file +itself provides the definition of the top-level API — no wrapper, no vtable +indirection, no runtime null-check. Calling `whal_Flash_Write(&dev, ...)` links +directly to the platform driver's implementation. + +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 the top-level wolfHAL + API (`whal_Flash_Write`, `whal_Uart_Send`, etc.). This file is shared across + all wolfHAL boards. + +2. **Board directory** (`hal/boards//`) — contains three files that fully + describe a board: + - `board.h` — includes the chip-specific wolfHAL driver headers and defines + any board-level pin/peripheral enums. + - `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`, the + `WHAL_CFG_*_API_MAPPING_*` flags, 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 top-level wolfHAL 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 whal_Flash_Write, whal_Uart_Send, etc.) + └─ #include "board.h" (resolved via -I to the board directory) + +hal/boards// + ├─ board.h (includes wolfHAL driver headers, pin enums) + ├─ board.c (device instances, hal_init, hal_prepare_boot) + └─ board.mk (WHAL_CFG_*_API_MAPPING_*, driver objects, RAM_CODE rules) +``` + +The `WHAL_CFG_*_API_MAPPING_*` flags cause each wolfHAL driver source to emit +its functions under the top-level API name. Since only one driver source per +device type is compiled, there is no conflict — and since no dispatch source +(e.g., `src/flash/flash.c`) is included, there is no vtable indirection. The +linker can garbage-collect any unused symbols 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` — Driver Headers and Pin Enums + +Include the chip-specific wolfHAL driver headers and declare any board-level +enums (pin indices, peripheral identifiers): + +```c +#ifndef WOLFHAL_BOARD_H +#define WOLFHAL_BOARD_H + +#include _rcc.h> +#include _flash.h> +#include _gpio.h> +#include _uart.h> + +/* GPIO pin indices (matches pin array in board.c) */ +enum { + BOARD_LED_PIN, + BOARD_UART_TX_PIN, + BOARD_UART_RX_PIN, + BOARD_PIN_COUNT, +}; + +#endif /* WOLFHAL_BOARD_H */ +``` + +### 2. `board.c` — Device Instances and Initialization + +Define the wolfHAL device instances and implement `hal_init` and `hal_prepare_boot` +using the top-level wolfHAL API. 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 = &(whal_Rcc_Cfg) { ... }, +}; + +/* Flash */ +whal_Flash g_wbFlash = { + .regmap = { .base = ..., .size = 0x400 }, + .cfg = &(whal_Flash_Cfg) { + .startAddr = 0x08000000, + .size = ..., + }, +}; + +#ifdef DEBUG_UART +whal_Gpio g_wbGpio = { ... }; +whal_Uart g_wbUart = { ... }; +#endif + +void hal_init(void) +{ + whal_Clock_Init(&g_wbClock); + whal_Flash_Init(&g_wbFlash); +#ifdef DEBUG_UART + whal_Gpio_Init(&g_wbGpio); + whal_Uart_Init(&g_wbUart); +#endif +} + +void hal_prepare_boot(void) +{ +#ifdef DEBUG_UART + whal_Uart_Deinit(&g_wbUart); + whal_Gpio_Deinit(&g_wbGpio); +#endif + whal_Flash_Deinit(&g_wbFlash); + whal_Clock_Deinit(&g_wbClock); +} +``` + +Note: the device instance's `.driver` field is intentionally left unset. With +API mapping, the top-level `whal_*_Init`/etc. symbols are the driver functions +themselves — there is no dispatch through a vtable. + +### 3. `board.mk` — Build Variables + +Provide the build-time configuration: API mapping flags, flash offset, linker +script, and the wolfHAL driver objects needed for your MCU family. **Do not +compile the dispatch source (`src//.c`)** — it would provide a +duplicate definition of the top-level API symbols. + +```makefile +ARCH_FLASH_OFFSET=0x08000000 +LSCRIPT_IN=hal/.ld + +# Bind wolfHAL driver sources directly to the top-level API symbols. +CFLAGS+=-DWHAL_CFG_CLOCK_API_MAPPING_ +CFLAGS+=-DWHAL_CFG_FLASH_API_MAPPING_ +CFLAGS+=-DWHAL_CFG_GPIO_API_MAPPING_ +CFLAGS+=-DWHAL_CFG_UART_API_MAPPING_ + +WOLFHAL_OBJS+=$(WOLFHAL_ROOT)/src/clock/_rcc.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 +``` + +Only one API mapping flag may be active per device type per build. + +### 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 top-level wolfHAL +API (`whal_Gpio_Set`, `whal_Uart_Send`) 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..eb54e6eacb --- /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_Clock_Enable(&g_wbClock, &flashClk); + whal_Stm32wbFlash_Ext_SetLatency(&g_wbFlash, WHAL_STM32WB_FLASH_LATENCY_3); + + whal_Clock_Init(&g_wbClock); + whal_Flash_Init(&g_wbFlash); + +#ifdef DEBUG_UART + for (size_t i = 0; i < CLOCK_COUNT; i++) { + whal_Clock_Enable(&g_wbClock, &g_clocks[i]); + } + + whal_Gpio_Init(&g_wbGpio); + whal_Uart_Init(&g_wbUart); +#endif +} + +void hal_prepare_boot(void) +{ +#ifdef DEBUG_UART + whal_Uart_Deinit(&g_wbUart); + whal_Gpio_Deinit(&g_wbGpio); + + for (size_t i = 0; i < CLOCK_COUNT; i++) { + whal_Clock_Disable(&g_wbClock, &g_clocks[i]); + } +#endif + + whal_Flash_Deinit(&g_wbFlash); + whal_Clock_Deinit(&g_wbClock); + + /* Reduce flash latency then disable flash clock */ + whal_Stm32wbFlash_Ext_SetLatency(&g_wbFlash, WHAL_STM32WB_FLASH_LATENCY_0); + whal_Clock_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..e7fc932ba3 --- /dev/null +++ b/hal/boards/stm32wb_nucleo/board.h @@ -0,0 +1,40 @@ +/* board.h + * + * wolfHAL board header 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 + */ + +#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, +}; + +#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..e9a12d5465 --- /dev/null +++ b/hal/boards/stm32wb_nucleo/board.mk @@ -0,0 +1,23 @@ +ARCH_FLASH_OFFSET=0x08000000 +LSCRIPT_IN=hal/stm32wb.ld + +CFLAGS+=-DWHAL_CFG_CLOCK_API_MAPPING_STM32WB_PLL +CFLAGS+=-DWHAL_CFG_FLASH_API_MAPPING_STM32WB +CFLAGS+=-DWHAL_CFG_GPIO_API_MAPPING_STM32WB +CFLAGS+=-DWHAL_CFG_UART_API_MAPPING_STM32WB + +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..05508cbdab --- /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) +{ + whal_Flash_Unlock(&g_wbFlash, 0, 0); +} + +void RAMFUNCTION hal_flash_lock(void) +{ + whal_Flash_Lock(&g_wbFlash, 0, 0); +} + +int RAMFUNCTION hal_flash_write(uint32_t address, const uint8_t *data, int len) +{ + return whal_Flash_Write(&g_wbFlash, (size_t)address, data, (size_t)len); +} + +int RAMFUNCTION hal_flash_erase(uint32_t address, int len) +{ + return whal_Flash_Erase(&g_wbFlash, (size_t)address, (size_t)len); +} + +#ifdef DEBUG_UART +void uart_write(const char *buf, unsigned int len) +{ + whal_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..a1823e3cc9 --- /dev/null +++ b/lib/wolfHAL @@ -0,0 +1 @@ +Subproject commit a1823e3cc996265765437f82899e8f90e54eca47 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..c2c15ac276 --- /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 */ + whal_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; + whal_Uart_Send(&g_wbUart, ver_buf, sizeof(ver_buf)); + + if ((version == 1) && (updv != 8)) { + /* LED off */ + whal_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 */ + whal_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 */