Skip to content

Commit 64f45fd

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 64f45fd

File tree

2 files changed

+107
-31
lines changed

2 files changed

+107
-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: 100 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,27 @@ 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 we are using custom RAM function relocator.
159+
* This relocator runs after RAM cleanup.
160+
* Size of the relocated 'locking' function isn't known but it doesn't matter
161+
* as long as at least entire aforementioned function is copied to RAM.
162+
*/
163+
#include <hal/nrf_rramc.h>
164+
165+
#define RRAMC_REGION_RWX_LSB 0
166+
#define RRAMC_REGION_RWX_WIDTH 3
167+
#define RRAMC_REGION_TO_LOCK_ADDR NRF_RRAMC->REGION[4].CONFIG
168+
#define RRAMC_REGION_TO_LOCK_ADDR_H (((uint32_t)(&(RRAMC_REGION_TO_LOCK_ADDR))) >> 16)
169+
#define RRAMC_REGION_TO_LOCK_ADDR_L (((uint32_t)(&(RRAMC_REGION_TO_LOCK_ADDR))) & 0x0000fffful)
170+
#endif /* CONFIG_MCUBOOT_DISABLE_SELF_RWX */
171+
151172
BOOT_LOG_MODULE_REGISTER(mcuboot);
152173

153174
void os_heap_init(void);
@@ -163,6 +184,84 @@ struct arm_vector_table {
163184
uint32_t reset;
164185
};
165186

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

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

0 commit comments

Comments
 (0)