Skip to content

Commit ae7d23b

Browse files
committed
Fix stm32h5 OTP readonly block rounding
F/1475
1 parent b28a97e commit ae7d23b

4 files changed

Lines changed: 92 additions & 8 deletions

File tree

hal/stm32h5.c

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include <string.h>
2626

2727
#include "hal.h"
28+
#include "hal_otp.h"
2829
#include "hal/stm32h5.h"
2930
#include "hal/armv8m_tz.h"
3031

@@ -764,20 +765,15 @@ void hal_prepare_boot(void)
764765
int hal_flash_otp_set_readonly(uint32_t flashAddress, uint16_t length)
765766
{
766767
uint32_t start_block = (flashAddress - FLASH_OTP_BASE) / FLASH_OTP_BLOCK_SIZE;
767-
uint32_t count = length / FLASH_OTP_BLOCK_SIZE;
768+
uint32_t count = hal_otp_blocks_for_length(length, FLASH_OTP_BLOCK_SIZE);
768769
uint32_t bmap = 0;
769770
unsigned int i;
770771
if (start_block + count > 32)
771772
return -1;
772773

773-
if ((length % FLASH_OTP_BLOCK_SIZE) != 0)
774-
{
775-
count++;
776-
}
777-
778774
/* Turn on the bits */
779775
for (i = start_block; i < (start_block + count); i++) {
780-
bmap |= (1 << i);
776+
bmap |= (1U << i);
781777
}
782778
/* Enable OTP write protection for the selected blocks */
783779
while ((bmap & FLASH_OTPBLR_CUR) != bmap) {

include/hal_otp.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#ifndef WOLFBOOT_HAL_OTP_H
2+
#define WOLFBOOT_HAL_OTP_H
3+
4+
#include <stdint.h>
5+
6+
static inline uint32_t hal_otp_blocks_for_length(uint32_t length,
7+
uint32_t block_size)
8+
{
9+
return (length + block_size - 1U) / block_size;
10+
}
11+
12+
#endif /* WOLFBOOT_HAL_OTP_H */

tools/unit-tests/Makefile

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ TESTS:=unit-parser unit-extflash unit-string unit-spi-flash unit-aes128 \
4949
unit-update-flash-enc unit-update-ram unit-pkcs11_store unit-psa_store unit-disk \
5050
unit-update-disk unit-multiboot unit-boot-x86-fsp unit-qspi-flash unit-tpm-rsa-exp \
5151
unit-image-nopart unit-image-sha384 unit-image-sha3-384 unit-store-sbrk \
52-
unit-tpm-blob unit-policy-sign unit-sdhci-response-bits
52+
unit-tpm-blob unit-policy-sign unit-sdhci-response-bits unit-hal-otp
5353

5454
all: $(TESTS)
5555

@@ -149,6 +149,9 @@ unit-sdhci-response-bits: ../../include/target.h unit-sdhci-response-bits.c
149149
gcc -o $@ $^ $(CFLAGS) -ffunction-sections -fdata-sections $(LDFLAGS) \
150150
-Wl,--gc-sections
151151

152+
unit-hal-otp: ../../include/target.h unit-hal-otp.c
153+
gcc -o $@ $^ $(CFLAGS) $(LDFLAGS)
154+
152155
unit-aes128: ../../include/target.h unit-extflash.c
153156
gcc -o $@ $^ $(CFLAGS) $(LDFLAGS)
154157

tools/unit-tests/unit-hal-otp.c

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/* unit-hal-otp.c
2+
*
3+
* Unit tests for OTP block rounding helpers.
4+
*
5+
* Copyright (C) 2026 wolfSSL Inc.
6+
*
7+
* This file is part of wolfBoot.
8+
*
9+
* wolfBoot is free software; you can redistribute it and/or modify
10+
* it under the terms of the GNU General Public License as published by
11+
* the Free Software Foundation; either version 3 of the License, or
12+
* (at your option) any later version.
13+
*
14+
* wolfBoot is distributed in the hope that it will be useful,
15+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
16+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17+
* GNU General Public License for more details.
18+
*
19+
* You should have received a copy of the GNU General Public License
20+
* along with this program; if not, write to the Free Software
21+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
22+
*/
23+
24+
#include <check.h>
25+
#include <stdint.h>
26+
27+
#include "../../include/hal_otp.h"
28+
29+
#define FLASH_OTP_BLOCK_SIZE 64U
30+
#define OTP_BLOCKS 32U
31+
32+
START_TEST(test_rounds_partial_block_before_bounds_check)
33+
{
34+
uint32_t start_block = OTP_BLOCKS - 1U;
35+
uint32_t count = hal_otp_blocks_for_length(1U, FLASH_OTP_BLOCK_SIZE);
36+
37+
ck_assert_uint_eq(count, 1U);
38+
ck_assert_uint_gt(start_block + count, OTP_BLOCKS - 1U);
39+
}
40+
END_TEST
41+
42+
START_TEST(test_exact_multiple_keeps_exact_block_count)
43+
{
44+
ck_assert_uint_eq(
45+
hal_otp_blocks_for_length(FLASH_OTP_BLOCK_SIZE * 2U, FLASH_OTP_BLOCK_SIZE),
46+
2U);
47+
}
48+
END_TEST
49+
50+
static Suite *hal_otp_suite(void)
51+
{
52+
Suite *s = suite_create("hal-otp");
53+
TCase *tc = tcase_create("rounding");
54+
55+
tcase_add_test(tc, test_rounds_partial_block_before_bounds_check);
56+
tcase_add_test(tc, test_exact_multiple_keeps_exact_block_count);
57+
suite_add_tcase(s, tc);
58+
59+
return s;
60+
}
61+
62+
int main(void)
63+
{
64+
int fails;
65+
Suite *s = hal_otp_suite();
66+
SRunner *sr = srunner_create(s);
67+
68+
srunner_run_all(sr, CK_NORMAL);
69+
fails = srunner_ntests_failed(sr);
70+
srunner_free(sr);
71+
72+
return fails;
73+
}

0 commit comments

Comments
 (0)