Skip to content

Commit 918b809

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 918b809

File tree

2 files changed

+110
-31
lines changed

2 files changed

+110
-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: 103 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,30 @@ 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_GAP_SIZE ((int) (__ramfunc_end - __ramfunc_region_start))
155+
156+
#if defined(CONFIG_MCUBOOT_DISABLE_SELF_RWX)
157+
/* Disabling R_X has to be done while running from RAM for obvious reasons.
158+
* Moreover as a last step before jumping to application it must work even after
159+
* RAM has been cleared, therefore we are using custom RAM function relocator.
160+
* This relocator runs after RAM cleanup.
161+
* Size of the relocated 'locking' function isn't known but it doesn't matter
162+
* as long as at least entire aforementioned function is copied to RAM.
163+
*/
164+
#include <hal/nrf_rramc.h>
165+
166+
#define RRAMC_REGION_RWX_LSB 0
167+
#define RRAMC_REGION_RWX_WIDTH 3
168+
#define RRAMC_REGION_TO_LOCK_ADDR NRF_RRAMC->REGION[4].CONFIG
169+
#define RRAMC_REGION_TO_LOCK_ADDR_H (((uint32_t)(&(RRAMC_REGION_TO_LOCK_ADDR))) >> 16)
170+
#define RRAMC_REGION_TO_LOCK_ADDR_L (((uint32_t)(&(RRAMC_REGION_TO_LOCK_ADDR))) & 0x0000fffful)
171+
#endif /* CONFIG_MCUBOOT_DISABLE_SELF_RWX */
172+
173+
174+
151175
BOOT_LOG_MODULE_REGISTER(mcuboot);
152176

153177
void os_heap_init(void);
@@ -163,6 +187,84 @@ struct arm_vector_table {
163187
uint32_t reset;
164188
};
165189

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

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

0 commit comments

Comments
 (0)