Skip to content

Commit 0902d9a

Browse files
committed
wolfhsm_flash_hal: model on psa_store sector-cache pattern for H5 ECC
e2e real HW tests with first and second boot persistant trip
1 parent c0df7c4 commit 0902d9a

2 files changed

Lines changed: 41 additions & 43 deletions

File tree

include/wolfboot/wolfhsm_flash_hal.h

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,6 @@
55
* This file is part of wolfBoot.
66
*/
77

8-
/*
9-
* Adapter that exposes wolfBoot's hal_flash_*() API as a wolfHSM whFlashCb,
10-
* letting the secure-side wolfHSM server persist its NVM in real flash
11-
* instead of the ramsim used during bring-up.
12-
*/
13-
148
#ifndef WOLFBOOT_WOLFHSM_FLASH_HAL_H
159
#define WOLFBOOT_WOLFHSM_FLASH_HAL_H
1610

@@ -20,14 +14,13 @@
2014

2115
#include "wolfhsm/wh_flash.h"
2216

17+
/* Per-call config / context for the adapter. base/size/partition_size are
18+
* the only client-visible fields; the cache lives inside the static
19+
* implementation in wolfhsm_flash_hal.c (mirroring psa_store.c). */
2320
typedef struct {
24-
uint32_t base; /* Absolute flash address of the wolfHSM NVM
25-
region (must be 8 KiB-aligned) */
26-
uint32_t size; /* Size of the region in bytes (>= 2 *
27-
partition_size, multiple of 8 KiB) */
28-
uint32_t partition_size; /* Per-partition size in bytes; wolfHSM uses
29-
two partitions (active + backup) for
30-
journaling. Must be a multiple of 8 KiB. */
21+
uint32_t base;
22+
uint32_t size;
23+
uint32_t partition_size;
3124
} whFlashH5Ctx;
3225

3326
extern const whFlashCb whFlashH5_Cb;

src/wolfhsm_flash_hal.c

Lines changed: 35 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,15 @@
1616
#include "wolfhsm/wh_error.h"
1717
#include "wolfhsm/wh_flash.h"
1818

19-
/*
20-
* STM32H5 page (= erase) size and program-quad-word size. The dual-bank
21-
* H5 erase granularity is 8 KiB; flash programming happens in 16-byte
22-
* quad-word units.
23-
*/
24-
#define WHFH5_SECTOR_SIZE (8U * 1024U)
25-
#define WHFH5_PROGRAM_UNIT 16U
19+
#define WHFH5_SECTOR_SIZE (8U * 1024U)
2620

21+
/* Sector-cached read-modify-erase-write, mirroring psa_store.c. STM32H5
22+
* flash programs in 16-byte quad-words with ECC; each quad-word can be
23+
* programmed exactly once between erases. wolfHSM issues 8-byte unit
24+
* writes which would otherwise re-program neighbouring qwords, so every
25+
* Program call here loads the affected sector into RAM, modifies it, and
26+
* rewrites the whole 8 KiB sector after an erase. */
27+
static uint8_t cached_sector[WHFH5_SECTOR_SIZE];
2728

2829
static int _Init(void *context, const void *config)
2930
{
@@ -55,18 +56,9 @@ static int _Cleanup(void *context)
5556
static uint32_t _PartitionSize(void *context)
5657
{
5758
whFlashH5Ctx *ctx = (whFlashH5Ctx *)context;
58-
if (ctx == NULL) {
59-
return 0U;
60-
}
61-
return ctx->partition_size;
59+
return (ctx == NULL) ? 0U : ctx->partition_size;
6260
}
6361

64-
/*
65-
* STM32H5 has a single global flash unlock; per-region lock/unlock isn't
66-
* available. Program/Erase wrap the unlock+op+lock cycle themselves, so
67-
* the wh_FlashUnit_Program helper's "WriteUnlock around batch of writes"
68-
* pattern is satisfied without per-call hardware action here.
69-
*/
7062
static int _WriteLock(void *context, uint32_t offset, uint32_t size)
7163
{
7264
(void)context;
@@ -103,7 +95,7 @@ static int _Program(void *context, uint32_t offset, uint32_t size,
10395
const uint8_t *data)
10496
{
10597
whFlashH5Ctx *ctx = (whFlashH5Ctx *)context;
106-
int rc;
98+
uint32_t written = 0U;
10799

108100
if (ctx == NULL || (size != 0U && data == NULL)) {
109101
return WH_ERROR_BADARGS;
@@ -114,16 +106,29 @@ static int _Program(void *context, uint32_t offset, uint32_t size,
114106
if (size == 0U) {
115107
return WH_ERROR_OK;
116108
}
117-
/* hal_flash_write programs in H5 quad-word (16 byte) chunks; partial
118-
* quad-words at either end fold the existing flash content so any
119-
* `size` is acceptable here. The H5 ECC rule ("each quad-word may be
120-
* programmed at most once between erases") is satisfied as long as
121-
* wolfHSM's unit writes don't share a quad-word, which holds for the
122-
* 32 KiB-aligned partitions / 8-byte units we use. */
123-
hal_flash_unlock();
124-
rc = hal_flash_write(ctx->base + offset, data, (int)size);
125-
hal_flash_lock();
126-
return (rc == 0) ? WH_ERROR_OK : WH_ERROR_ABORTED;
109+
110+
while (written < size) {
111+
uint32_t in_sector_off = (offset + written) % WHFH5_SECTOR_SIZE;
112+
uint32_t sector_base = (offset + written) - in_sector_off;
113+
uint32_t chunk = WHFH5_SECTOR_SIZE - in_sector_off;
114+
if (chunk > size - written) {
115+
chunk = size - written;
116+
}
117+
118+
memcpy(cached_sector,
119+
(const uint8_t *)(ctx->base + sector_base),
120+
WHFH5_SECTOR_SIZE);
121+
memcpy(cached_sector + in_sector_off, data + written, chunk);
122+
123+
hal_flash_unlock();
124+
hal_flash_erase(ctx->base + sector_base, WHFH5_SECTOR_SIZE);
125+
hal_flash_write(ctx->base + sector_base, cached_sector,
126+
WHFH5_SECTOR_SIZE);
127+
hal_flash_lock();
128+
129+
written += chunk;
130+
}
131+
return WH_ERROR_OK;
127132
}
128133

129134
static int _Erase(void *context, uint32_t offset, uint32_t size)
@@ -171,9 +176,9 @@ static int _Verify(void *context, uint32_t offset, uint32_t size,
171176

172177
static int _BlankCheck(void *context, uint32_t offset, uint32_t size)
173178
{
174-
whFlashH5Ctx *ctx = (whFlashH5Ctx *)context;
179+
whFlashH5Ctx *ctx = (whFlashH5Ctx *)context;
175180
const uint8_t *p;
176-
uint32_t i;
181+
uint32_t i;
177182

178183
if (ctx == NULL) {
179184
return WH_ERROR_BADARGS;

0 commit comments

Comments
 (0)