Skip to content

Commit b795cce

Browse files
authored
Merge pull request #617 from mattia-moffa/20251023-h5-update-fix
Fix STM32H5 update
2 parents a93f2b7 + 70d25f4 commit b795cce

File tree

12 files changed

+219
-67
lines changed

12 files changed

+219
-67
lines changed

config/examples/stm32h5-tz-dualbank-otp-lms.config

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ DUALBANK_SWAP?=1
2121
WOLFBOOT_PARTITION_SIZE?=0xA0000
2222
WOLFBOOT_SECTOR_SIZE?=0x2000
2323
WOLFBOOT_PARTITION_BOOT_ADDRESS?=0x08060000
24-
WOLFBOOT_PARTITION_UPDATE_ADDRESS?=0x08160000
24+
WOLFBOOT_PARTITION_UPDATE_ADDRESS?=0x0C160000
2525
WOLFBOOT_PARTITION_SWAP_ADDRESS?=0xFFFFFFFF
2626
FLAGS_HOME=0
2727
DISABLE_BACKUP=0

config/examples/stm32h5-tz-dualbank-otp.config

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ DUALBANK_SWAP?=1
2121
WOLFBOOT_PARTITION_SIZE?=0xA0000
2222
WOLFBOOT_SECTOR_SIZE?=0x2000
2323
WOLFBOOT_PARTITION_BOOT_ADDRESS?=0x08060000
24-
WOLFBOOT_PARTITION_UPDATE_ADDRESS?=0x08160000
24+
WOLFBOOT_PARTITION_UPDATE_ADDRESS?=0x0C160000
2525
WOLFBOOT_PARTITION_SWAP_ADDRESS?=0xFFFFFFFF
2626
FLAGS_HOME=0
2727
DISABLE_BACKUP=0

config/examples/stm32h5-tz.config

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ DUALBANK_SWAP?=0
2121
WOLFBOOT_PARTITION_SIZE?=0xA0000
2222
WOLFBOOT_SECTOR_SIZE?=0x2000
2323
WOLFBOOT_PARTITION_BOOT_ADDRESS?=0x08060000
24-
WOLFBOOT_PARTITION_UPDATE_ADDRESS?=0x08100000
25-
WOLFBOOT_PARTITION_SWAP_ADDRESS?=0x081A0000
24+
WOLFBOOT_PARTITION_UPDATE_ADDRESS?=0x0C100000
25+
WOLFBOOT_PARTITION_SWAP_ADDRESS?=0x0C1A0000
2626
FLAGS_HOME=0
2727
DISABLE_BACKUP=0
2828
WOLFCRYPT_TZ=1

docs/API.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,3 +66,35 @@ the two images again.
6666
For more information about the update process, see [Firmware Update](firmware_update.md)
6767

6868
For the image format, see [Firmware Image](firmware_image.md)
69+
70+
## NSC API
71+
72+
If you're running wolfBoot on an ARM TrustZone-enabled device (see for example
73+
[STM32-TZ](STM32-TZ.md)) you may wish to run your application in non-secure
74+
mode, while keeping the UPDATE and SWAP partitions in the secure domain. In
75+
order to accomplish this, any operation by the application that requires access
76+
to those partitions needs to be performed via wolfBoot code running in the
77+
secure domain. For this purpose, wolfBoot provides Non-Secure Callable (NSC)
78+
APIs that allow code running in the non-secure domain to call into the secure
79+
domain managed by wolfBoot.
80+
81+
These APIs are listed below.
82+
83+
- `void wolfBoot_nsc_success(void)`: wrapper for `wolfBoot_success()`
84+
- `void wolfBoot_nsc_update_trigger(void)`: wrapper for
85+
`wolfBoot_update_trigger()`
86+
- `uint32_t wolfBoot_nsc_get_image_version(uint8_t part)`: wrapper for
87+
`wolfBoot_get_image_version()`
88+
- `uint32_t wolfBoot_nsc_current_firmware_version(void)`: wrapper for
89+
`wolfBoot_current_firmware_version()`
90+
- `uint32_t wolfBoot_nsc_update_firmware_version(void)`: wrapper for
91+
`wolfBoot_update_firmware_version()`
92+
- `int wolfBoot_nsc_get_partition_state(uint8_t part, uint8_t *st)`: wrapper
93+
for `wolfBoot_get_partition_state()`
94+
- `int wolfBoot_nsc_erase_update(uint32_t address, uint32_t len)`: allows the
95+
application to erase the update partition in secure mode. The `address`
96+
parameter is an offset from the beginning of the partition.
97+
- `int wolfBoot_nsc_write_update(uint32_t address, const uint8_t *buf, uint32_t
98+
len)`: allows the application to write to the update partition in secure
99+
mode. The `address` parameter is an offset from the beginning of the
100+
partition.

docs/STM32-TZ.md

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,12 @@ image header size must be supplied as an environment variable. For example:
5555
IMAGE_HEADER_SIZE=1024 ./tools/keytools/sign --sha256 --ecc256 myapp.bin wolfboot_signing_private_key.der 1
5656
```
5757

58+
### NSC API
59+
60+
wolfBoot provides a few Non-Secure Callable functions to allow a non-secure
61+
application to perform certain operations that must be run from the secure
62+
domain. For more information, see [API](API.md#nsc-api).
63+
5864
### Example using STM32L552
5965

6066
- Copy the example configuration for STM32-L5 with support for wolfCrypt in
@@ -192,7 +198,7 @@ OPTION BYTES BANK: 2
192198
193199
Boot Configuration:
194200
195-
NSBOOTADD : 0x80400 (0x8040000)
201+
NSBOOTADD : 0x80600 (0x8060000)
196202
NSBOOT_LOCK : 0xC3 (The SWAP_BANK and NSBOOTADD can still be modified following their individual rules.)
197203
SECBOOT_LOCK : 0xC3 (The BOOT_UBE, SWAP_BANK and SECBOOTADD can still be modified following their individual rules.)
198204
SECBOOTADD : 0xC0000 (0xC000000)
@@ -201,7 +207,7 @@ OPTION BYTES BANK: 3
201207
Bank1 - Flash watermark area definition:
202208
203209
SECWM1_STRT : 0x0 (0x8000000)
204-
SECWM1_END : 0x1F (0x803E000)
210+
SECWM1_END : 0x2F (0x805e000)
205211
206212
Write sector group protection 1:
207213
@@ -211,7 +217,7 @@ OPTION BYTES BANK: 4
211217
Bank2 - Flash watermark area definition:
212218
213219
SECWM2_STRT : 0x0 (0x08100000)
214-
SECWM2_END : 0x1F (0x0813e000)
220+
SECWM2_END : 0x7F (0x081fe0000)
215221
216222
Write sector group protection 2:
217223
@@ -251,7 +257,7 @@ OPTION BYTES BANK: 9
251257

252258
```
253259
STM32_Programmer_CLI -c port=swd -d wolfboot.bin 0x0C000000
254-
STM32_Programmer_CLI -c port=swd -d test-app/image_v1_signed.bin 0x08040000
260+
STM32_Programmer_CLI -c port=swd -d test-app/image_v1_signed.bin 0x08060000
255261
```
256262

257263
- After rebooting, the LED on the board should turn on sequentially:

docs/Targets.md

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -175,10 +175,10 @@ The example configuration for this scenario is available in [/config/examples/st
175175
- User Option Bytes requirement (with STM32CubeProgrammer tool - see below for instructions)
176176

177177
```
178-
TZEN = 1 System with TrustZone-M enabled
179-
DBANK = 1 Dual bank mode
180-
SECWM1_PSTRT=0x0 SECWM1_PEND=0x7F All 128 pages of internal Flash Bank1 set as secure
181-
SECWM2_PSTRT=0x1 SECWM2_PEND=0x0 No page of internal Flash Bank2 set as secure, hence Bank2 non-secure
178+
TZEN = 1 System with TrustZone-M enabled
179+
DBANK = 1 Dual bank mode
180+
SECWM1_STRT=0x0 SECWM1_END=0x7F All 128 pages of internal Flash Bank1 set as secure
181+
SECWM2_STRT=0x1 SECWM2_END=0x0 No page of internal Flash Bank2 set as secure, hence Bank2 non-secure
182182
```
183183

184184
- NOTE: STM32CubeProgrammer V2.3.0 is required (v2.4.0 has a known bug for STM32L5)
@@ -189,7 +189,7 @@ SECWM2_PSTRT=0x1 SECWM2_PEND=0x0 No page of internal Flash Bank2 set as secur
189189
2. `make`
190190
3. Prepare board with option bytes configuration reported above
191191
- `STM32_Programmer_CLI -c port=swd mode=hotplug -ob TZEN=1 DBANK=1`
192-
- `STM32_Programmer_CLI -c port=swd mode=hotplug -ob SECWM1_PSTRT=0x0 SECWM1_PEND=0x7F SECWM2_PSTRT=0x1 SECWM2_PEND=0x0`
192+
- `STM32_Programmer_CLI -c port=swd mode=hotplug -ob SECWM1_STRT=0x0 SECWM1_END=0x7F SECWM2_STRT=0x1 SECWM2_END=0x0`
193193
4. flash wolfBoot.bin to 0x0c00 0000
194194
- `STM32_Programmer_CLI -c port=swd -d ./wolfboot.bin 0x0C000000`
195195
5. flash .\test-app\image_v1_signed.bin to 0x0804 0000
@@ -316,10 +316,10 @@ SRAM memories into two parts:
316316
- User Option Bytes requirement (with STM32CubeProgrammer tool - see below for instructions)
317317

318318
```
319-
TZEN = 1 System with TrustZone-M enabled
320-
DBANK = 1 Dual bank mode
321-
SECWM1_PSTRT=0x0 SECWM1_PEND=0x7F All 128 pages of internal Flash Bank1 set as secure
322-
SECWM2_PSTRT=0x1 SECWM2_PEND=0x0 No page of internal Flash Bank2 set as secure, hence Bank2 non-secure
319+
TZEN = 1 System with TrustZone-M enabled
320+
DBANK = 1 Dual bank mode
321+
SECWM1_STRT=0x0 SECWM1_END=0x7F All 128 pages of internal Flash Bank1 set as secure
322+
SECWM2_STRT=0x1 SECWM2_END=0x0 No page of internal Flash Bank2 set as secure, hence Bank2 non-secure
323323
```
324324

325325
- NOTE: STM32CubeProgrammer V2.8.0 or newer is required
@@ -330,7 +330,7 @@ SECWM2_PSTRT=0x1 SECWM2_PEND=0x0 No page of internal Flash Bank2 set as secur
330330
2. `make TZEN=1`
331331
3. Prepare board with option bytes configuration reported above
332332
- `STM32_Programmer_CLI -c port=swd mode=hotplug -ob TZEN=1 DBANK=1`
333-
- `STM32_Programmer_CLI -c port=swd mode=hotplug -ob SECWM1_PSTRT=0x0 SECWM1_PEND=0x7F SECWM2_PSTRT=0x1 SECWM2_PEND=0x0`
333+
- `STM32_Programmer_CLI -c port=swd mode=hotplug -ob SECWM1_STRT=0x0 SECWM1_END=0x7F SECWM2_STRT=0x1 SECWM2_END=0x0`
334334
4. flash wolfBoot.bin to 0x0c000000
335335
- `STM32_Programmer_CLI -c port=swd -d ./wolfboot.bin 0x0C000000`
336336
5. flash .\test-app\image_v1_signed.bin to 0x08010000
@@ -915,7 +915,7 @@ The example configuration for this scenario is available in [/config/examples/st
915915
`STM32_Programmer_CLI -c port=swd -ob TZEN=0xB4`
916916

917917
- set the option bytes to enable flash secure protection of first 384KB and remainder as non-secure:
918-
`STM32_Programmer_CLI -c port=swd -ob SECWM1_PSTRT=0x0 SECWM1_PEND=0x2F SECWM2_PSTRT=0x2F SECWM2_PEND=0x0`
918+
`STM32_Programmer_CLI -c port=swd -ob SECWM1_STRT=0x0 SECWM1_END=0x2F SECWM2_STRT=0x0 SECWM2_END=0x7F`
919919

920920
- flash the wolfboot image to the secure partition:
921921
`STM32_Programmer_CLI -c port=swd -d wolfboot.bin 0x0C000000`
@@ -925,6 +925,19 @@ The example configuration for this scenario is available in [/config/examples/st
925925

926926
For a full list of all the option bytes tested with this configuration, refer to [STM32-TZ.md](/docs/STM32-TZ.md).
927927

928+
You can use the "update" command and XMODEM to send a newly signed update (see docs/flash-OTP.md) or use the steps below using the STM32_Programmer:
929+
930+
```sh
931+
IMAGE_HEADER_SIZE=1024 tools/keytools/sign --ecc256 test-app/image.bin wolfboot_signing_private_key.der 2
932+
echo -n "pBOOT" > trigger_magic.bin
933+
./tools/bin-assemble/bin-assemble \
934+
update.bin \
935+
0x0 test-app/image_v2_signed.bin \
936+
0x9FFFB trigger_magic.bin
937+
STM32_Programmer_CLI -c port=swd -d update.bin 0x0C100000
938+
```
939+
940+
928941
### Scenario 2: TrustZone Enabled, wolfCrypt as secure engine for NS applications
929942

930943
This is similar to Scenario 1, but also includes wolfCrypt in secure mode, and
@@ -975,7 +988,7 @@ To initiate an update, sign a new version of the app and upload the v3 to the up
975988
on the second bank:
976989

977990
```sh
978-
tools/keytools/sign --ecc256 test-app/image.bin wolfboot_signing_private_key.der 3
991+
IMAGE_HEADER_SIZE=1024 tools/keytools/sign --ecc256 test-app/image.bin wolfboot_signing_private_key.der 3
979992
STM32_Programmer_CLI -c port=swd -d test-app/image_v3_signed.bin 0x08160000
980993
```
981994

hal/stm32_tz.c

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -96,19 +96,21 @@ void hal_tz_claim_nonsecure_area(uint32_t address, int len)
9696
uint32_t reg;
9797
uint32_t end = address + len;
9898
uint32_t start_address = address;
99+
uint32_t start_page_n;
99100
uint32_t bank = 0;
100101
int pos;
101102

102103
if (!is_range_nonsecure(address, len))
103104
return;
104105

105106
if (address < FLASH_BANK2_BASE) {
106-
page_n = (address - ARCH_FLASH_OFFSET) / FLASH_PAGE_SIZE;
107+
start_page_n = (address - ARCH_FLASH_OFFSET) / FLASH_PAGE_SIZE;
107108
bank = 0;
108109
} else {
109-
page_n = (address - FLASH_BANK2_BASE) / FLASH_PAGE_SIZE;
110+
start_page_n = (address - FLASH_BANK2_BASE) / FLASH_PAGE_SIZE;
110111
bank = 1;
111112
}
113+
page_n = start_page_n;
112114
#ifdef TARGET_stm32h5
113115
/* Take into account current swap configuration */
114116
if ((FLASH_OPTSR_CUR & FLASH_OPTSR_SWAP_BANK) >> 31)
@@ -129,13 +131,14 @@ void hal_tz_claim_nonsecure_area(uint32_t address, int len)
129131
page_n++;
130132
}
131133
address = start_address;
134+
page_n = start_page_n;
132135
while (address < end) {
133136
/* Erase claimed non-secure page, in secure mode */
134137
#ifndef TARGET_stm32h5
135138
reg = FLASH_CR & (~((FLASH_CR_PNB_MASK << FLASH_CR_PNB_SHIFT) | FLASH_CR_PER | FLASH_CR_BKER | FLASH_CR_PG | FLASH_CR_MER1 | FLASH_CR_MER2));
136139
FLASH_CR = reg | ((page_n << FLASH_CR_PNB_SHIFT) | FLASH_CR_PER);
137140
#else
138-
reg = FLASH_CR & (~((FLASH_CR_PNB_MASK << FLASH_CR_PNB_SHIFT) | FLASH_CR_SER | FLASH_CR_BER | FLASH_CR_PG | FLASH_CR_MER));
141+
reg = FLASH_CR & (~((FLASH_CR_PNB_MASK << FLASH_CR_PNB_SHIFT) | FLASH_CR_SER | FLASH_CR_BER | FLASH_CR_PG | FLASH_CR_MER | FLASH_CR_BKSEL));
139142
FLASH_CR = reg | ((page_n << FLASH_CR_PNB_SHIFT) | FLASH_CR_SER | (bank << 31));
140143
#endif
141144

@@ -162,8 +165,11 @@ void hal_tz_release_nonsecure_area(void)
162165
{
163166
#ifndef DUALBANK_SWAP
164167
int i;
165-
for (i = 0; i < FLASH_SECBB_NREGS; i++)
168+
/* Set all banks as non-secure */
169+
for (i = 0; i < FLASH_SECBB_NREGS; i++) {
170+
FLASH_SECBB1[i] = 0;
166171
FLASH_SECBB2[i] = 0;
172+
}
167173
#else
168174
uint32_t addr;
169175
int bank_swp = 0;

hal/stm32h5.c

Lines changed: 30 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -32,15 +32,11 @@
3232
#define PLL_SRC_HSE 1
3333

3434
#if TZ_SECURE()
35-
36-
/* This function assumes that the boot and the update
37-
* partitions are at the same address in the two banks,
38-
* regardless if DUALBANK_SWAP is active or not.
39-
*/
4035
static int is_flash_nonsecure(uint32_t address)
4136
{
42-
uint32_t in_bank_offset = (address & 0x000FFFFF);
43-
if (in_bank_offset >= (WOLFBOOT_PARTITION_BOOT_ADDRESS - FLASHMEM_ADDRESS_SPACE)) {
37+
if (address >= WOLFBOOT_PARTITION_BOOT_ADDRESS &&
38+
address < WOLFBOOT_PARTITION_BOOT_ADDRESS +
39+
WOLFBOOT_PARTITION_SIZE) {
4440
return 1;
4541
}
4642
return 0;
@@ -189,6 +185,7 @@ void RAMFUNCTION hal_flash_opt_lock(void)
189185

190186
int RAMFUNCTION hal_flash_erase(uint32_t address, int len)
191187
{
188+
uint32_t start_address;
192189
uint32_t end_address;
193190
uint32_t p;
194191

@@ -199,35 +196,50 @@ int RAMFUNCTION hal_flash_erase(uint32_t address, int len)
199196
if (address < 0x08000000)
200197
return -1;
201198

202-
end_address = address + len - 1;
203-
for (p = address; p < end_address; p += FLASH_PAGE_SIZE) {
199+
#if TZ_SECURE()
200+
if (address & FLASH_SECURE_MMAP_BIT) {
201+
/* Get address in non-secure address space */
202+
start_address = address & ~FLASH_SECURE_MMAP_BIT;
203+
}
204+
else {
205+
if (is_flash_nonsecure(address)) {
206+
hal_tz_claim_nonsecure_area(address, len);
207+
}
208+
start_address = address;
209+
}
210+
#else
211+
start_address = address;
212+
#endif
213+
214+
end_address = start_address + len - 1;
215+
for (p = start_address; p < end_address; p += FLASH_PAGE_SIZE) {
204216
uint32_t reg;
205217
uint32_t base;
206218
uint32_t bnksel = 0;
207219
base = FLASHMEM_ADDRESS_SPACE;
208-
reg = FLASH_CR & (~((FLASH_CR_PNB_MASK << FLASH_CR_PNB_SHIFT) | FLASH_CR_BER));
209-
if(p >= (FLASH_BANK2_BASE) && (p <= (FLASH_TOP) ))
220+
reg = FLASH_CR & (~((FLASH_CR_PNB_MASK << FLASH_CR_PNB_SHIFT) | FLASH_CR_SER | FLASH_CR_BER | FLASH_CR_PG | FLASH_CR_MER | FLASH_CR_BKSEL));
221+
if (p >= FLASH_BANK2_BASE && p <= FLASH_TOP)
210222
{
211223
base = FLASH_BANK2_BASE;
212224
bnksel = 1;
213225
}
214-
#if TZ_SECURE()
215-
/* When in secure mode, skip erasing non-secure pages: will be erased upon claim */
216-
if (is_flash_nonsecure(address)) {
217-
return 0;
218-
}
219-
#endif
220226
/* Check for swapped banks to invert bnksel */
221227
if ((FLASH_OPTSR_CUR & FLASH_OPTSR_SWAP_BANK) >> 31)
222228
bnksel = !bnksel;
223229
reg |= ((((p - base) >> 13) << FLASH_CR_PNB_SHIFT) | FLASH_CR_SER | (bnksel << 31));
224230
FLASH_CR = reg;
225231
ISB();
226232
FLASH_CR |= FLASH_CR_STRT;
227-
hal_flash_wait_complete(0);
233+
hal_flash_wait_complete(bnksel);
228234
}
229235
/* If the erase operation is completed, disable the associated bits */
230236
FLASH_CR &= ~FLASH_CR_SER ;
237+
238+
#if TZ_SECURE()
239+
if (!(address & FLASH_SECURE_MMAP_BIT) && is_flash_nonsecure(address)) {
240+
hal_tz_release_nonsecure_area();
241+
}
242+
#endif
231243
return 0;
232244
}
233245

hal/stm32h5.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
#endif
5050

5151
#define FLASH_SECURE_MMAP_BASE (0x0C000000)
52+
#define FLASH_SECURE_MMAP_BIT (0x04000000)
5253

5354
#define RCC_CR (*(volatile uint32_t *)(RCC_BASE + 0x00)) /* RM0481 - Table 108 */
5455
#define RCC_CR_PLL3RDY (1 << 29) /* RM0481 - Table 108 */

include/wolfboot/wolfboot.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -420,14 +420,23 @@ int wolfBoot_erase_encrypt_key(void);
420420
*/
421421

422422
/* Call wolfBoot_success from non-secure application */
423-
424423
__attribute__((cmse_nonsecure_entry))
425424
void wolfBoot_nsc_success(void);
426425

427426
/* Call wolfBoot_update_trigger from non-secure application */
428427
__attribute__((cmse_nonsecure_entry))
429428
void wolfBoot_nsc_update_trigger(void);
430429

430+
/* Call wolfBoot_get_image_version from non-secure application */
431+
__attribute__((cmse_nonsecure_entry))
432+
uint32_t wolfBoot_nsc_get_image_version(uint8_t part);
433+
#define wolfBoot_nsc_current_firmware_version() wolfBoot_nsc_get_image_version(PART_BOOT)
434+
#define wolfBoot_nsc_update_firmware_version() wolfBoot_nsc_get_image_version(PART_UPDATE)
435+
436+
/* Call wolfBoot_get_partition_state from non-secure application */
437+
__attribute__((cmse_nonsecure_entry))
438+
int wolfBoot_nsc_get_partition_state(uint8_t part, uint8_t *st);
439+
431440
/* Erase one or more sectors in the update partition.
432441
* - address: offset within the update partition ('0' corresponds to PARTITION_UPDATE_ADDRESS)
433442
* - len: size, in bytes

0 commit comments

Comments
 (0)