@@ -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_NCS_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_NCS_MCUBOOT_DISABLE_SELF_RWX */
169+
151170BOOT_LOG_MODULE_REGISTER (mcuboot );
152171
153172void 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_NCS_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_NCS_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_NCS_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_NCS_MCUBOOT_DISABLE_SELF_RWX */
259+ : " r0 ", " r1 ", " r2 ", " r3 ", " r4 ", " r5 ", " r6 ", " memory "
260+ );
261+ }
262+
166263static void do_boot (struct boot_rsp * rsp )
167264{
168265 /* vt is static as it shall not land on the stack,
@@ -273,37 +370,7 @@ static void do_boot(struct boot_rsp *rsp)
273370 __set_CONTROL (0x00 ); /* application will configures core on its own */
274371 __ISB ();
275372#endif
276- #if CONFIG_MCUBOOT_CLEANUP_RAM
277- __asm__ volatile (
278- /* vt->reset -> r0 */
279- " mov r0, %0\n"
280- /* base to write -> r1 */
281- " mov r1, %1\n"
282- /* size to write -> r2 */
283- " mov r2, %2\n"
284- /* value to write -> r3 */
285- " mov r3, %3\n"
286- "clear:\n"
287- " str r3, [r1]\n"
288- " add r1, r1, #4\n"
289- " sub r2, r2, #4\n"
290- " cbz r2, out\n"
291- " b clear\n"
292- "out:\n"
293- " dsb\n"
294- #if CONFIG_MCUBOOT_INFINITE_LOOP_AFTER_RAM_CLEANUP
295- " b out\n"
296- #endif /*CONFIG_MCUBOOT_INFINITE_LOOP_AFTER_RAM_CLEANUP */
297- /* jump to reset vector of an app */
298- " bx r0\n"
299- :
300- : "r" (vt -> reset ), "i" (CONFIG_SRAM_BASE_ADDRESS ),
301- "i" (CONFIG_SRAM_SIZE * 1024 ), "i" (0 )
302- : "r0" , "r1" , "r2" , "r3" , "memory"
303- );
304- #else
305- ((void (* )(void ))vt -> reset )();
306- #endif
373+ jump_in (vt -> reset );
307374}
308375
309376#elif defined(CONFIG_XTENSA ) || defined(CONFIG_RISCV )
0 commit comments