@@ -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+
151178BOOT_LOG_MODULE_REGISTER (mcuboot );
152179
153180void 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+
166274static 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