Skip to content

Commit 4280ea8

Browse files
committed
tests: bootloader: NSIB MCUBoot locks
complete set of tests for region 3 and 4 lockouts. Signed-off-by: Mateusz Michalek <[email protected]>
1 parent b022fea commit 4280ea8

File tree

10 files changed

+295
-110
lines changed

10 files changed

+295
-110
lines changed

subsys/bootloader/Kconfig

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,13 +105,28 @@ config SB_CLEANUP_RAM
105105
help
106106
Sets contents of memory to 0 before jumping to application.
107107

108+
config SB_INFINITE_LOOP_AFTER_RAM_CLEANUP
109+
bool "Infinite loop after RAM cleanup"
110+
depends on SB_CLEANUP_RAM
111+
help
112+
Verification option that keeps execution in infinite loop after
113+
RAM cleanup has been performed.
114+
108115
config SB_DISABLE_SELF_RWX
109116
bool "Disable read and execution on self NVM"
110117
depends on (SOC_NRF54L15_CPUAPP || SOC_NRF54L05_CPUAPP || SOC_NRF54L10_CPUAPP) && !FPROTECT_ALLOW_COMBINED_REGIONS
111118
help
112119
Sets RRAMC's BOOTCONF region protection before jumping to application.
113120
It disables reads writes and execution memory area which holds NSIB.
114121

122+
config SB_DISABLE_NEXT_W
123+
bool "Disable writes for next stage"
124+
depends on (SOC_NRF54L15_CPUAPP || SOC_NRF54L05_CPUAPP || SOC_NRF54L10_CPUAPP) && !FPROTECT
125+
help
126+
NSIB disables writes on next stage in bootloading chain.
127+
It uses RRAMC's region 4 and is limited to 31KB.
128+
129+
115130
endif # IS_SECURE_BOOTLOADER
116131

117132
config IS_BOOTLOADER_IMG

subsys/bootloader/bl_boot/bl_boot.c

Lines changed: 132 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,51 @@
1919
#include <hal/nrf_gpio.h>
2020
#endif
2121

22+
#include <zephyr/linker/linker-defs.h>
23+
#define CLEANUP_RAM_GAP_START ((int)__ramfunc_region_start)
24+
#define CLEANUP_RAM_GAP_SIZE ((int) (__ramfunc_end - __ramfunc_region_start))
25+
26+
#if defined(CONFIG_SB_DISABLE_NEXT_W)
27+
#include <hal/nrf_rramc.h>
28+
#define RRAMC_REGION_FOR_NEXT_W 4
29+
#define NRF_RRAM_REGION_SIZE_UNIT 0x400
30+
#define NRF_RRAM_REGION_ADDRESS_RESOLUTION 0x400
31+
#define NEXT_W_SIZE_KB (PM_MCUBOOT_SIZE / NRF_RRAM_REGION_SIZE_UNIT)
32+
33+
BUILD_ASSERT((PM_MCUBOOT_ADDRESS % NRF_RRAM_REGION_ADDRESS_RESOLUTION) == 0,
34+
"Start of protected region is not aligned");
35+
36+
BUILD_ASSERT((PM_MCUBOOT_SIZE % NRF_RRAM_REGION_SIZE_UNIT) == 0,
37+
"Size of protected region is not aligned");
38+
39+
BUILD_ASSERT(NEXT_W_SIZE_KB < 31,
40+
"Size of requested protection is too big");
41+
42+
static int disable_next_w(void)
43+
{
44+
nrf_rramc_region_config_t config = {
45+
.address = PM_MCUBOOT_ADDRESS,
46+
.permissions = NRF_RRAMC_REGION_PERM_READ_MASK |
47+
NRF_RRAMC_REGION_PERM_EXECUTE_MASK,
48+
.writeonce = false,
49+
.lock = false,
50+
.size_kb = NEXT_W_SIZE_KB,
51+
};
52+
53+
nrf_rramc_region_config_set(NRF_RRAMC, RRAMC_REGION_FOR_NEXT_W, &config);
54+
nrf_rramc_region_config_get(NRF_RRAMC, RRAMC_REGION_FOR_NEXT_W, &config);
55+
if (config.permissions & (NRF_RRAMC_REGION_PERM_WRITE_MASK)) {
56+
return -ENOSPC;
57+
}
58+
if (config.size_kb != NEXT_W_SIZE_KB) {
59+
return -ENOSPC;
60+
}
61+
62+
return 0;
63+
}
64+
65+
#endif
66+
2267
#if defined(CONFIG_SB_DISABLE_SELF_RWX)
2368
/* Disabling R_X has to be done while running from RAM for obvious reasons.
2469
* Moreover as a last step before jumping to application it must work even after
@@ -29,15 +74,92 @@
2974
*/
3075
#include <hal/nrf_rramc.h>
3176

32-
#define FUNCTION_BUFFER_LEN 64
3377
#define RRAMC_REGION_RWX_LSB 0
3478
#define RRAMC_REGION_RWX_WIDTH 3
3579
#define RRAMC_REGION_TO_LOCK_ADDR NRF_RRAMC->REGION[3].CONFIG
3680
#define RRAMC_REGION_TO_LOCK_ADDR_H (((uint32_t)(&(RRAMC_REGION_TO_LOCK_ADDR))) >> 16)
3781
#define RRAMC_REGION_TO_LOCK_ADDR_L (((uint32_t)(&(RRAMC_REGION_TO_LOCK_ADDR))) & 0x0000fffful)
38-
static uint8_t ram_exec_buf[FUNCTION_BUFFER_LEN];
3982
#endif /* CONFIG_SB_DISABLE_SELF_RWX */
4083

84+
static void __ramfunc jump_in(uint32_t reset)
85+
{
86+
__asm__ volatile (
87+
88+
/* vector_table[1] -> r0 */
89+
" mov r0, %0\n"
90+
#ifdef CONFIG_SB_CLEANUP_RAM
91+
/* Base to write -> r1 */
92+
" mov r1, %1\n"
93+
/* Size to write -> r2 */
94+
" mov r2, %2\n"
95+
/* Value to write -> r3 */
96+
" movw r3, %5\n"
97+
/* gap start */
98+
" mov r4, %3\n"
99+
/* gap size */
100+
" mov r5, %4\n"
101+
"clear:\n"
102+
" subs r6, r4, r1\n"
103+
" cbnz r6, skip_gap\n"
104+
" add r1, r5\n"
105+
"skip_gap:\n"
106+
" str r3, [r1]\n"
107+
" add r1, r1, #1\n"
108+
" sub r2, r2, #1\n"
109+
" cbz r2, clear_end\n"
110+
" b clear\n"
111+
"clear_end:\n"
112+
" dsb\n"
113+
#ifdef CONFIG_SB_INFINITE_LOOP_AFTER_RAM_CLEANUP
114+
" b clear_end\n"
115+
#endif /*CONFIG_SB_INFINITE_LOOP_AFTER_RAM_CLEANUP */
116+
#endif /* CONFIG_SB_CLEANUP_RAM */
117+
118+
#ifdef CONFIG_SB_DISABLE_SELF_RWX
119+
".thumb_func\n"
120+
"bootconf_disable_rwx:\n"
121+
" movw r1, %6\n"
122+
" movt r1, %7\n"
123+
" ldr r2, [r1]\n"
124+
/* Size of the region should be set at this point
125+
* by provisioning through BOOTCONF.
126+
* If not, set it according partition size.
127+
*/
128+
" ands r4, r2, %12\n"
129+
" cbnz r4, clear_rwx\n"
130+
" movt r2, %8\n"
131+
"clear_rwx:\n"
132+
" bfc r2, %9, %10\n"
133+
/* Disallow further modifications */
134+
" orr r2, %11\n"
135+
" str r2, [r1]\n"
136+
" dsb\n"
137+
/* Next assembly line is important for current function */
138+
139+
#endif /* CONFIG_SB_DISABLE_SELF_RWX */
140+
141+
/* Jump to reset vector of an app */
142+
" bx r0\n"
143+
:
144+
: "r" (reset),
145+
"i" (CONFIG_SRAM_BASE_ADDRESS),
146+
"i" (CONFIG_SRAM_SIZE * 1024),
147+
"r" (CLEANUP_RAM_GAP_START),
148+
"r" (CLEANUP_RAM_GAP_SIZE),
149+
"i" (0)
150+
#ifdef CONFIG_SB_DISABLE_SELF_RWX
151+
,"i" (RRAMC_REGION_TO_LOCK_ADDR_L),
152+
"i" (RRAMC_REGION_TO_LOCK_ADDR_H),
153+
"i" (CONFIG_PM_PARTITION_SIZE_B0_IMAGE / 1024),
154+
"i" (RRAMC_REGION_RWX_LSB),
155+
"i" (RRAMC_REGION_RWX_WIDTH),
156+
"i" (RRAMC_REGION_CONFIG_LOCK_Msk),
157+
"i" (RRAMC_REGION_CONFIG_SIZE_Msk)
158+
#endif /* CONFIG_SB_DISABLE_SELF_RWX */
159+
: "r0", "r1", "r2", "r3", "r4", "r5", "r6", "memory"
160+
);
161+
}
162+
41163
#ifdef CONFIG_UART_NRFX_UARTE
42164
static void uninit_used_uarte(NRF_UARTE_Type *p_reg)
43165
{
@@ -163,6 +285,13 @@ void bl_boot(const struct fw_info *fw_info)
163285
VTOR = fw_info->address;
164286
uint32_t *vector_table = (uint32_t *)fw_info->address;
165287

288+
#if defined(CONFIG_SB_DISABLE_NEXT_W)
289+
if (disable_next_w()) {
290+
printk("Unable to disable writes on next stage.");
291+
return;
292+
}
293+
#endif
294+
166295
#if defined(CONFIG_BUILTIN_STACK_GUARD) && \
167296
defined(CONFIG_CPU_CORTEX_M_HAS_SPLIM)
168297
/* Reset limit registers to avoid inflicting stack overflow on image
@@ -175,96 +304,7 @@ void bl_boot(const struct fw_info *fw_info)
175304
__set_MSP(vector_table[0]);
176305
__set_PSP(0);
177306

178-
__asm__ volatile (
179-
/* vector_table[1] -> r0 */
180-
" mov r0, %0\n"
181-
#ifdef CONFIG_SB_CLEANUP_RAM
182-
/* Base to write -> r1 */
183-
" mov r1, %1\n"
184-
/* Size to write -> r2 */
185-
" mov r2, %2\n"
186-
/* Value to write -> r3 */
187-
" movw r3, %3\n"
188-
"clear:\n"
189-
" str r3, [r1]\n"
190-
" add r1, r1, #4\n"
191-
" sub r2, r2, #4\n"
192-
" cbz r2, out\n"
193-
" b clear\n"
194-
"out:\n"
195-
" dsb\n"
196-
#endif /* CONFIG_SB_CLEANUP_RAM */
197-
198-
#ifdef CONFIG_SB_DISABLE_SELF_RWX
199-
/* FUNCTION_BUFFER_LEN */
200-
" movw r4, %4\n"
201-
/* Address of ram_exec_buf goes to r2 */
202-
" mov r2, %5\n"
203-
" movw r3, :lower16:bootconf_disable_rwx\n"
204-
" movt r3, :upper16:bootconf_disable_rwx\n"
205-
/* Adjust address for thumb */
206-
" and r3, #0xfffffffe\n"
207-
/* Address of ram_exec_buf also goes to r5 */
208-
" mov r5, %5\n"
209-
/* Adjust buffer address for thumb */
210-
" orr r5, #0x1\n"
211-
/* End of the copy address in r4 */
212-
" add r4, r2\n"
213-
"ram_cpy:\n"
214-
/* Read and increment */
215-
" ldrb r1, [r3], #1\n"
216-
/* Write and increment */
217-
" strb r1, [r2], #1\n"
218-
/* Check if end address is reached */
219-
" cmp r2, r4\n"
220-
" bne ram_cpy\n"
221-
" dsb\n"
222-
/* Jump to ram */
223-
" bx r5\n"
224-
/* CODE_UNREACHABLE */
225-
226-
".thumb_func\n"
227-
"bootconf_disable_rwx:\n"
228-
" movw r1, %6\n"
229-
" movt r1, %7\n"
230-
" ldr r2, [r1]\n"
231-
/* Size of the region should be set at this point
232-
* by provisioning through BOOTCONF.
233-
* If not, set it according partition size.
234-
*/
235-
" ands r4, r2, %12\n"
236-
" cbnz r4, clear_rwx\n"
237-
" movt r2, %8\n"
238-
"clear_rwx:\n"
239-
" bfc r2, %9, %10\n"
240-
/* Disallow further modifications */
241-
" orr r2, %11\n"
242-
" str r2, [r1]\n"
243-
" dsb\n"
244-
/* Next assembly line is important for current function */
245-
246-
#endif /* CONFIG_SB_DISABLE_SELF_RWX */
247-
248-
/* Jump to reset vector of an app */
249-
" bx r0\n"
250-
:
251-
: "r" (vector_table[1]),
252-
"i" (CONFIG_SRAM_BASE_ADDRESS),
253-
"i" (CONFIG_SRAM_SIZE * 1024),
254-
"i" (0)
255-
#ifdef CONFIG_SB_DISABLE_SELF_RWX
256-
, "i" (FUNCTION_BUFFER_LEN),
257-
"r" (ram_exec_buf),
258-
"i" (RRAMC_REGION_TO_LOCK_ADDR_L),
259-
"i" (RRAMC_REGION_TO_LOCK_ADDR_H),
260-
"i" (CONFIG_PM_PARTITION_SIZE_B0_IMAGE / 1024),
261-
"i" (RRAMC_REGION_RWX_LSB),
262-
"i" (RRAMC_REGION_RWX_WIDTH),
263-
"i" (RRAMC_REGION_CONFIG_LOCK_Msk),
264-
"i" (RRAMC_REGION_CONFIG_SIZE_Msk)
265-
#endif /* CONFIG_SB_DISABLE_SELF_RWX */
266-
: "r0", "r1", "r2", "r3", "r4", "r5", "memory"
267-
);
307+
jump_in((vector_table[1]));
268308

269309
CODE_UNREACHABLE;
270310
}

tests/subsys/bootloader/b0_lock/testcase.yaml

Lines changed: 0 additions & 11 deletions
This file was deleted.
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#
2+
# Copyright (c) 2022 Nordic Semiconductor
3+
#
4+
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
5+
#
6+
7+
config TEST_B0_LOCK_READS
8+
bool "Enable PSA backend and dependencies"
9+
help
10+
Reads are disabled after writes has been disabled, therefore testing against reads
11+
implies portion of the memory cannot be accessed at all.
12+
In case this symbol isn't selected, tests against writes are performed.
13+
14+
config TEST_B0_LOCK_REGION
15+
int "Region number"
16+
range 3 4
17+
default 3
18+
help
19+
Region 3 is used for NSIB protection. Other one for MCUBoot.
20+
21+
22+
menu "Zephyr"
23+
source "Kconfig.zephyr"
24+
endmenu

0 commit comments

Comments
 (0)