Skip to content

Commit 827b39d

Browse files
committed
[nrf noup] boot: zephyr: Disable self RWX
Disables read write and execute on mcuboots NVM at the end of execution. Signed-off-by: Mateusz Michalek <[email protected]>
1 parent d69621e commit 827b39d

File tree

2 files changed

+116
-31
lines changed

2 files changed

+116
-31
lines changed

boot/zephyr/Kconfig

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -472,6 +472,13 @@ config MCUBOOT_CLEANUP_RAM
472472
help
473473
Sets contents of memory to 0 before jumping to application.
474474

475+
config MCUBOOT_DISABLE_SELF_RWX
476+
bool "Disable read and execution on self NVM"
477+
depends on SOC_NRF54L15_CPUAPP && !FPROTECT
478+
help
479+
Sets RRAMC's region no.4 protection before jumping to application.
480+
It disables reads writes and execution memory area which holds MCUBOOT.
481+
475482
config MCUBOOT_INFINITE_LOOP_AFTER_RAM_CLEANUP
476483
bool "Infinite loop after RAM cleanup"
477484
depends on MCUBOOT_CLEANUP_RAM

boot/zephyr/main.c

Lines changed: 109 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,33 @@ K_SEM_DEFINE(boot_log_sem, 1, 1);
148148
#include <nrf_cleanup.h>
149149
#endif
150150

151+
#include <zephyr/linker/linker-defs.h>
152+
#define CLEANUP_RAM_GAP_START ((int)__ramfunc_region_start)
153+
#define CLEANUP_RAM_GAP_END ((int)__ramfunc_end)
154+
#define CLEANUP_RAM_FIRST_START (CONFIG_SRAM_BASE_ADDRESS)
155+
#define CLEANUP_RAM_FIRST_SIZE (CLEANUP_RAM_GAP_START)
156+
#define CLEANUP_RAM_SECOND_START (CLEANUP_RAM_GAP_END)
157+
#define CLEANUP_RAM_SECOND_SIZE (CONFIG_SRAM_SIZE * 1024 - CLEANUP_RAM_GAP_END)
158+
159+
#if defined(CONFIG_MCUBOOT_DISABLE_SELF_RWX)
160+
/* Disabling R_X has to be done while running from RAM for obvious reasons.
161+
* Moreover as a last step before jumping to application it must work even after
162+
* RAM has been cleared, therefore we are using custom RAM function relocator.
163+
* This relocator runs after RAM cleanup.
164+
* Size of the relocated 'locking' function isn't known but it doesn't matter
165+
* as long as at least entire aforementioned function is copied to RAM.
166+
*/
167+
#include <hal/nrf_rramc.h>
168+
169+
#define RRAMC_REGION_RWX_LSB 0
170+
#define RRAMC_REGION_RWX_WIDTH 3
171+
#define RRAMC_REGION_TO_LOCK_ADDR NRF_RRAMC->REGION[4].CONFIG
172+
#define RRAMC_REGION_TO_LOCK_ADDR_H (((uint32_t)(&(RRAMC_REGION_TO_LOCK_ADDR))) >> 16)
173+
#define RRAMC_REGION_TO_LOCK_ADDR_L (((uint32_t)(&(RRAMC_REGION_TO_LOCK_ADDR))) & 0x0000fffful)
174+
#endif /* CONFIG_MCUBOOT_DISABLE_SELF_RWX */
175+
176+
177+
151178
BOOT_LOG_MODULE_REGISTER(mcuboot);
152179

153180
void os_heap_init(void);
@@ -163,6 +190,87 @@ struct arm_vector_table {
163190
uint32_t reset;
164191
};
165192

193+
static void __ramfunc jump_in(uint32_t vector_table)
194+
{
195+
__asm__ volatile (
196+
197+
/* vector_table[1] -> r0 */
198+
" mov r0, %0\n"
199+
#ifdef CONFIG_MCUBOOT_CLEANUP_RAM
200+
/* Base to write -> r1 */
201+
" mov r1, %1\n"
202+
/* Size to write -> r2 */
203+
" mov r2, %2\n"
204+
/* Value to write -> r3 */
205+
" movw r3, %5\n"
206+
"clear_first:\n"
207+
" str r3, [r1]\n"
208+
" add r1, r1, #4\n"
209+
" sub r2, r2, #4\n"
210+
" cbz r2, clear_next\n"
211+
" b clear_first\n"
212+
"clear_next:\n"
213+
/* Base to write -> r1 */
214+
" mov r1, %3\n"
215+
/* Size to write -> r2 */
216+
" mov r2, %4\n"
217+
"clear_second:\n"
218+
" str r3, [r1]\n"
219+
" add r1, r1, #4\n"
220+
" sub r2, r2, #4\n"
221+
" cbz r2, out\n"
222+
" b clear_second\n"
223+
"out:\n"
224+
" dsb\n"
225+
#if CONFIG_MCUBOOT_INFINITE_LOOP_AFTER_RAM_CLEANUP
226+
" b out\n"
227+
#endif /*CONFIG_MCUBOOT_INFINITE_LOOP_AFTER_RAM_CLEANUP */
228+
#endif /* CONFIG_MCUBOOT_CLEANUP_RAM */
229+
#ifdef CONFIG_MCUBOOT_DISABLE_SELF_RWX
230+
".thumb_func\n"
231+
"region_disable_rwx:\n"
232+
" movw r1, %6\n"
233+
" movt r1, %7\n"
234+
" ldr r2, [r1]\n"
235+
/* Size of the region should be set at this point
236+
* by NSIB's DISABLE_NEXT_W.
237+
* If not, set it according partition size.
238+
*/
239+
" ands r4, r2, %12\n"
240+
" cbnz r4, clear_rwx\n"
241+
" movt r2, %8\n"
242+
"clear_rwx:\n"
243+
" bfc r2, %9, %10\n"
244+
/* Disallow further modifications */
245+
" orr r2, %11\n"
246+
" str r2, [r1]\n"
247+
" dsb\n"
248+
/* Next assembly line is important for current function */
249+
250+
#endif /* CONFIG_MCUBOOT_DISABLE_SELF_RWX */
251+
252+
/* Jump to reset vector of an app */
253+
" bx r0\n"
254+
:
255+
: "r" (vector_table),
256+
"r" (CLEANUP_RAM_FIRST_START),
257+
"r" (CLEANUP_RAM_FIRST_SIZE),
258+
"r" (CLEANUP_RAM_SECOND_START),
259+
"r" (CLEANUP_RAM_SECOND_SIZE),
260+
"i" (0)
261+
#ifdef CONFIG_MCUBOOT_DISABLE_SELF_RWX
262+
,"i" (RRAMC_REGION_TO_LOCK_ADDR_L),
263+
"i" (RRAMC_REGION_TO_LOCK_ADDR_H),
264+
"i" (CONFIG_PM_PARTITION_SIZE_B0_IMAGE / 1024),
265+
"i" (RRAMC_REGION_RWX_LSB),
266+
"i" (RRAMC_REGION_RWX_WIDTH),
267+
"i" (RRAMC_REGION_CONFIG_LOCK_Msk),
268+
"i" (RRAMC_REGION_CONFIG_SIZE_Msk)
269+
#endif /* CONFIG_MCUBOOT_DISABLE_SELF_RWX */
270+
: "r0", "r1", "r2", "r3", "r4", "r5", "memory"
271+
);
272+
}
273+
166274
static void do_boot(struct boot_rsp *rsp)
167275
{
168276
/* vt is static as it shall not land on the stack,
@@ -276,37 +384,7 @@ static void do_boot(struct boot_rsp *rsp)
276384
__set_CONTROL(0x00); /* application will configures core on its own */
277385
__ISB();
278386
#endif
279-
#if CONFIG_MCUBOOT_CLEANUP_RAM
280-
__asm__ volatile (
281-
/* vt->reset -> r0 */
282-
" mov r0, %0\n"
283-
/* base to write -> r1 */
284-
" mov r1, %1\n"
285-
/* size to write -> r2 */
286-
" mov r2, %2\n"
287-
/* value to write -> r3 */
288-
" mov r3, %3\n"
289-
"clear:\n"
290-
" str r3, [r1]\n"
291-
" add r1, r1, #4\n"
292-
" sub r2, r2, #4\n"
293-
" cbz r2, out\n"
294-
" b clear\n"
295-
"out:\n"
296-
" dsb\n"
297-
#if CONFIG_MCUBOOT_INFINITE_LOOP_AFTER_RAM_CLEANUP
298-
" b out\n"
299-
#endif /*CONFIG_MCUBOOT_INFINITE_LOOP_AFTER_RAM_CLEANUP */
300-
/* jump to reset vector of an app */
301-
" bx r0\n"
302-
:
303-
: "r" (vt->reset), "i" (CONFIG_SRAM_BASE_ADDRESS),
304-
"i" (CONFIG_SRAM_SIZE * 1024), "i" (0)
305-
: "r0", "r1", "r2", "r3", "memory"
306-
);
307-
#else
308-
((void (*)(void))vt->reset)();
309-
#endif
387+
jump_in(vt->reset);
310388
}
311389

312390
#elif defined(CONFIG_XTENSA) || defined(CONFIG_RISCV)

0 commit comments

Comments
 (0)