Skip to content

Commit a25c7c4

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 c72ed15 commit a25c7c4

File tree

2 files changed

+105
-31
lines changed

2 files changed

+105
-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: 98 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,25 @@ 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_SIZE ((int) (__ramfunc_end - __ramfunc_region_start))
154+
155+
#if defined(CONFIG_MCUBOOT_DISABLE_SELF_RWX)
156+
/* Disabling R_X has to be done while running from RAM for obvious reasons.
157+
* Moreover as a last step before jumping to application it must work even after
158+
* RAM has been cleared, therefore these operations are performed while executing from RAM.
159+
* RAM cleanup ommits portion of the memory where code lives.
160+
*/
161+
#include <hal/nrf_rramc.h>
162+
163+
#define RRAMC_REGION_RWX_LSB 0
164+
#define RRAMC_REGION_RWX_WIDTH 3
165+
#define RRAMC_REGION_TO_LOCK_ADDR NRF_RRAMC->REGION[4].CONFIG
166+
#define RRAMC_REGION_TO_LOCK_ADDR_H (((uint32_t)(&(RRAMC_REGION_TO_LOCK_ADDR))) >> 16)
167+
#define RRAMC_REGION_TO_LOCK_ADDR_L (((uint32_t)(&(RRAMC_REGION_TO_LOCK_ADDR))) & 0x0000fffful)
168+
#endif /* CONFIG_MCUBOOT_DISABLE_SELF_RWX */
169+
151170
BOOT_LOG_MODULE_REGISTER(mcuboot);
152171

153172
void os_heap_init(void);
@@ -163,6 +182,84 @@ struct arm_vector_table {
163182
uint32_t reset;
164183
};
165184

185+
static void __ramfunc jump_in(uint32_t reset)
186+
{
187+
__asm__ volatile (
188+
/* reset -> r0 */
189+
" mov r0, %0\n"
190+
#ifdef CONFIG_MCUBOOT_CLEANUP_RAM
191+
/* Base to write -> r1 */
192+
" mov r1, %1\n"
193+
/* Size to write -> r2 */
194+
" mov r2, %2\n"
195+
/* Value to write -> r3 */
196+
" movw r3, %5\n"
197+
/* gap start */
198+
" mov r4, %3\n"
199+
/* gap size */
200+
" mov r5, %4\n"
201+
"clear:\n"
202+
" subs r6, r4, r1\n"
203+
" cbnz r6, skip_gap\n"
204+
" add r1, r5\n"
205+
"skip_gap:\n"
206+
" str r3, [r1]\n"
207+
" add r1, r1, #1\n"
208+
" sub r2, r2, #1\n"
209+
" cbz r2, clear_end\n"
210+
" b clear\n"
211+
"clear_end:\n"
212+
" dsb\n"
213+
#ifdef CONFIG_MCUBOOT_INFINITE_LOOP_AFTER_RAM_CLEANUP
214+
" b clear_end\n"
215+
#endif /*CONFIG_MCUBOOT_INFINITE_LOOP_AFTER_RAM_CLEANUP */
216+
#endif /* CONFIG_MCUBOOT_CLEANUP_RAM */
217+
218+
#ifdef CONFIG_MCUBOOT_DISABLE_SELF_RWX
219+
".thumb_func\n"
220+
"region_disable_rwx:\n"
221+
" movw r1, %6\n"
222+
" movt r1, %7\n"
223+
" ldr r2, [r1]\n"
224+
/* Size of the region should be set at this point
225+
* by NSIB's DISABLE_NEXT_W.
226+
* If not, set it according partition size.
227+
*/
228+
" ands r4, r2, %12\n"
229+
" cbnz r4, clear_rwx\n"
230+
" movt r2, %8\n"
231+
"clear_rwx:\n"
232+
" bfc r2, %9, %10\n"
233+
/* Disallow further modifications */
234+
" orr r2, %11\n"
235+
" str r2, [r1]\n"
236+
" dsb\n"
237+
/* Next assembly line is important for current function */
238+
239+
#endif /* CONFIG_MCUBOOT_DISABLE_SELF_RWX */
240+
241+
/* Jump to reset vector of an app */
242+
" bx r0\n"
243+
:
244+
: "r" (reset),
245+
"r" (CONFIG_SRAM_BASE_ADDRESS),
246+
"i" (CONFIG_SRAM_SIZE * 1024),
247+
"r" (CLEANUP_RAM_GAP_START),
248+
"r" (CLEANUP_RAM_GAP_SIZE),
249+
"i" (0)
250+
#ifdef CONFIG_MCUBOOT_DISABLE_SELF_RWX
251+
, "i" (RRAMC_REGION_TO_LOCK_ADDR_L),
252+
"i" (RRAMC_REGION_TO_LOCK_ADDR_H),
253+
"i" (CONFIG_PM_PARTITION_SIZE_B0_IMAGE / 1024),
254+
"i" (RRAMC_REGION_RWX_LSB),
255+
"i" (RRAMC_REGION_RWX_WIDTH),
256+
"i" (RRAMC_REGION_CONFIG_LOCK_Msk),
257+
"i" (RRAMC_REGION_CONFIG_SIZE_Msk)
258+
#endif /* CONFIG_MCUBOOT_DISABLE_SELF_RWX */
259+
: "r0", "r1", "r2", "r3", "r4", "r5", "r6", "memory"
260+
);
261+
}
262+
166263
static void do_boot(struct boot_rsp *rsp)
167264
{
168265
/* vt is static as it shall not land on the stack,
@@ -276,37 +373,7 @@ static void do_boot(struct boot_rsp *rsp)
276373
__set_CONTROL(0x00); /* application will configures core on its own */
277374
__ISB();
278375
#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
376+
jump_in(vt->reset);
310377
}
311378

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

0 commit comments

Comments
 (0)