1919#include <hal/nrf_gpio.h>
2020#endif
2121
22+ #include <zephyr/linker/linker-defs.h>
23+ #define CLEANUP_RAM_GAP_START ((int)__ramfunc_region_start)
24+ #define CLEANUP_RAM_GAP_SIZE ((int) (__ramfunc_end - __ramfunc_region_start))
25+
26+ #if defined(CONFIG_SB_DISABLE_NEXT_W )
27+ #include <hal/nrf_rramc.h>
28+ #define RRAMC_REGION_FOR_NEXT_W 4
29+ #define NRF_RRAM_REGION_SIZE_UNIT 0x400
30+ #define NRF_RRAM_REGION_ADDRESS_RESOLUTION 0x400
31+ #define NEXT_W_SIZE_KB (PM_MCUBOOT_SIZE / NRF_RRAM_REGION_SIZE_UNIT)
32+
33+ BUILD_ASSERT ((PM_MCUBOOT_ADDRESS % NRF_RRAM_REGION_ADDRESS_RESOLUTION ) == 0 ,
34+ "Start of protected region is not aligned" );
35+
36+ BUILD_ASSERT ((PM_MCUBOOT_SIZE % NRF_RRAM_REGION_SIZE_UNIT ) == 0 ,
37+ "Size of protected region is not aligned" );
38+
39+ BUILD_ASSERT (NEXT_W_SIZE_KB < 31 ,
40+ "Size of requested protection is too big" );
41+
42+ static int disable_next_w (void )
43+ {
44+ nrf_rramc_region_config_t config = {
45+ .address = PM_MCUBOOT_ADDRESS ,
46+ .permissions = NRF_RRAMC_REGION_PERM_READ_MASK |
47+ NRF_RRAMC_REGION_PERM_EXECUTE_MASK ,
48+ .writeonce = false,
49+ .lock = false,
50+ .size_kb = NEXT_W_SIZE_KB ,
51+ };
52+
53+ nrf_rramc_region_config_set (NRF_RRAMC , RRAMC_REGION_FOR_NEXT_W , & config );
54+ nrf_rramc_region_config_get (NRF_RRAMC , RRAMC_REGION_FOR_NEXT_W , & config );
55+ if (config .permissions & (NRF_RRAMC_REGION_PERM_WRITE_MASK )) {
56+ return - ENOSPC ;
57+ }
58+ if (config .size_kb != NEXT_W_SIZE_KB ) {
59+ return - ENOSPC ;
60+ }
61+
62+ return 0 ;
63+ }
64+
65+ #endif
66+
2267#if defined(CONFIG_SB_DISABLE_SELF_RWX )
2368/* Disabling R_X has to be done while running from RAM for obvious reasons.
2469 * Moreover as a last step before jumping to application it must work even after
25- * RAM has been cleared, therefore we are using custom RAM function relocator.
26- * This relocator runs after RAM cleanup.
27- * Size of the relocated 'locking' function isn't known but it doesn't matter
28- * as long as at least entire aforementioned function is copied to RAM.
70+ * RAM has been cleared, therefore these operations are performed while executing from RAM.
71+ * RAM cleanup ommits portion of the memory where code lives.
2972 */
3073#include <hal/nrf_rramc.h>
3174
32- #define FUNCTION_BUFFER_LEN 64
3375#define RRAMC_REGION_RWX_LSB 0
3476#define RRAMC_REGION_RWX_WIDTH 3
3577#define RRAMC_REGION_TO_LOCK_ADDR NRF_RRAMC->REGION[3].CONFIG
3678#define RRAMC_REGION_TO_LOCK_ADDR_H (((uint32_t)(&(RRAMC_REGION_TO_LOCK_ADDR))) >> 16)
3779#define RRAMC_REGION_TO_LOCK_ADDR_L (((uint32_t)(&(RRAMC_REGION_TO_LOCK_ADDR))) & 0x0000fffful)
38- static uint8_t ram_exec_buf [FUNCTION_BUFFER_LEN ];
3980#endif /* CONFIG_SB_DISABLE_SELF_RWX */
4081
82+ static void __ramfunc jump_in (uint32_t reset )
83+ {
84+ __asm__ volatile (
85+ /* reset -> r0 */
86+ " mov r0, %0\n"
87+ #ifdef CONFIG_SB_CLEANUP_RAM
88+ /* Base to write -> r1 */
89+ " mov r1, %1\n"
90+ /* Size to write -> r2 */
91+ " mov r2, %2\n"
92+ /* Value to write -> r3 */
93+ " movw r3, %5\n"
94+ /* gap start */
95+ " mov r4, %3\n"
96+ /* gap size */
97+ " mov r5, %4\n"
98+ "clear:\n"
99+ " subs r6, r4, r1\n"
100+ " cbnz r6, skip_gap\n"
101+ " add r1, r5\n"
102+ "skip_gap:\n"
103+ " str r3, [r1]\n"
104+ " add r1, r1, #1\n"
105+ " sub r2, r2, #1\n"
106+ " cbz r2, clear_end\n"
107+ " b clear\n"
108+ "clear_end:\n"
109+ " dsb\n"
110+ #ifdef CONFIG_SB_INFINITE_LOOP_AFTER_RAM_CLEANUP
111+ " b clear_end\n"
112+ #endif /* CONFIG_SB_INFINITE_LOOP_AFTER_RAM_CLEANUP */
113+ #endif /* CONFIG_SB_CLEANUP_RAM */
114+
115+ #ifdef CONFIG_SB_DISABLE_SELF_RWX
116+ ".thumb_func \n "
117+ "bootconf_disable_rwx :\n "
118+ " movw r1 , %6 \n "
119+ " movt r1 , %7 \n "
120+ " ldr r2 , [r1 ]\n "
121+ /* Size of the region should be set at this point
122+ * by provisioning through BOOTCONF.
123+ * If not, set it according partition size.
124+ */
125+ " ands r4 , r2 , %12 \n "
126+ " cbnz r4 , clear_rwx \n "
127+ " movt r2 , %8 \n "
128+ " clear_rwx :\n "
129+ " bfc r2 , %9 , %10 \n "
130+ /* Disallow further modifications */
131+ " orr r2 , %11 \n "
132+ " str r2 , [r1 ]\n "
133+ " dsb \n "
134+ /* Next assembly line is important for current function */
135+
136+ #endif /* CONFIG_SB_DISABLE_SELF_RWX */
137+
138+ /* Jump to reset vector of an app */
139+ " bx r0 \n "
140+ :
141+ : " r " (reset),
142+ " i " (CONFIG_SRAM_BASE_ADDRESS),
143+ " i " (CONFIG_SRAM_SIZE * 1024),
144+ " r " (CLEANUP_RAM_GAP_START),
145+ " r " (CLEANUP_RAM_GAP_SIZE),
146+ " i " (0)
147+ #ifdef CONFIG_SB_DISABLE_SELF_RWX
148+ , " i " (RRAMC_REGION_TO_LOCK_ADDR_L),
149+ " i " (RRAMC_REGION_TO_LOCK_ADDR_H),
150+ " i " (CONFIG_PM_PARTITION_SIZE_B0_IMAGE / 1024),
151+ " i " (RRAMC_REGION_RWX_LSB),
152+ " i " (RRAMC_REGION_RWX_WIDTH),
153+ " i " (RRAMC_REGION_CONFIG_LOCK_Msk),
154+ " i " (RRAMC_REGION_CONFIG_SIZE_Msk)
155+ #endif /* CONFIG_SB_DISABLE_SELF_RWX */
156+ : " r0 ", " r1 ", " r2 ", " r3 ", " r4 ", " r5 ", " r6 ", " memory "
157+ );
158+ }
159+
41160#ifdef CONFIG_UART_NRFX_UARTE
42161static void uninit_used_uarte (NRF_UARTE_Type * p_reg )
43162{
@@ -163,6 +282,13 @@ void bl_boot(const struct fw_info *fw_info)
163282 VTOR = fw_info -> address ;
164283 uint32_t * vector_table = (uint32_t * )fw_info -> address ;
165284
285+ #if defined(CONFIG_SB_DISABLE_NEXT_W )
286+ if (disable_next_w ()) {
287+ printk ("Unable to disable writes on next stage." );
288+ return ;
289+ }
290+ #endif
291+
166292#if defined(CONFIG_BUILTIN_STACK_GUARD ) && \
167293 defined(CONFIG_CPU_CORTEX_M_HAS_SPLIM )
168294 /* Reset limit registers to avoid inflicting stack overflow on image
@@ -175,96 +301,7 @@ void bl_boot(const struct fw_info *fw_info)
175301 __set_MSP (vector_table [0 ]);
176302 __set_PSP (0 );
177303
178- __asm__ volatile (
179- /* vector_table[1] -> r0 */
180- " mov r0, %0\n"
181- #ifdef CONFIG_SB_CLEANUP_RAM
182- /* Base to write -> r1 */
183- " mov r1, %1\n"
184- /* Size to write -> r2 */
185- " mov r2, %2\n"
186- /* Value to write -> r3 */
187- " movw r3, %3\n"
188- "clear:\n"
189- " str r3, [r1]\n"
190- " add r1, r1, #4\n"
191- " sub r2, r2, #4\n"
192- " cbz r2, out\n"
193- " b clear\n"
194- "out:\n"
195- " dsb\n"
196- #endif /* CONFIG_SB_CLEANUP_RAM */
197-
198- #ifdef CONFIG_SB_DISABLE_SELF_RWX
199- /* FUNCTION_BUFFER_LEN */
200- " movw r4, %4\n"
201- /* Address of ram_exec_buf goes to r2 */
202- " mov r2, %5\n"
203- " movw r3, :lower16:bootconf_disable_rwx\n"
204- " movt r3, :upper16:bootconf_disable_rwx\n"
205- /* Adjust address for thumb */
206- " and r3, #0xfffffffe\n"
207- /* Address of ram_exec_buf also goes to r5 */
208- " mov r5, %5\n"
209- /* Adjust buffer address for thumb */
210- " orr r5, #0x1\n"
211- /* End of the copy address in r4 */
212- " add r4, r2\n"
213- "ram_cpy:\n"
214- /* Read and increment */
215- " ldrb r1, [r3], #1\n"
216- /* Write and increment */
217- " strb r1, [r2], #1\n"
218- /* Check if end address is reached */
219- " cmp r2, r4\n"
220- " bne ram_cpy\n"
221- " dsb\n"
222- /* Jump to ram */
223- " bx r5\n"
224- /* CODE_UNREACHABLE */
225-
226- ".thumb_func\n"
227- "bootconf_disable_rwx:\n"
228- " movw r1, %6\n"
229- " movt r1, %7\n"
230- " ldr r2, [r1]\n"
231- /* Size of the region should be set at this point
232- * by provisioning through BOOTCONF.
233- * If not, set it according partition size.
234- */
235- " ands r4, r2, %12\n"
236- " cbnz r4, clear_rwx\n"
237- " movt r2, %8\n"
238- "clear_rwx:\n"
239- " bfc r2, %9, %10\n"
240- /* Disallow further modifications */
241- " orr r2, %11\n"
242- " str r2, [r1]\n"
243- " dsb\n"
244- /* Next assembly line is important for current function */
245-
246- #endif /* CONFIG_SB_DISABLE_SELF_RWX */
247-
248- /* Jump to reset vector of an app */
249- " bx r0 \n "
250- :
251- : "r" (vector_table [1 ]),
252- "i" (CONFIG_SRAM_BASE_ADDRESS ),
253- "i" (CONFIG_SRAM_SIZE * 1024 ),
254- "i" (0 )
255- #ifdef CONFIG_SB_DISABLE_SELF_RWX
256- , "i" (FUNCTION_BUFFER_LEN ),
257- "r" (ram_exec_buf ),
258- "i" (RRAMC_REGION_TO_LOCK_ADDR_L ),
259- "i" (RRAMC_REGION_TO_LOCK_ADDR_H ),
260- "i" (CONFIG_PM_PARTITION_SIZE_B0_IMAGE / 1024 ),
261- "i" (RRAMC_REGION_RWX_LSB ),
262- "i" (RRAMC_REGION_RWX_WIDTH ),
263- "i" (RRAMC_REGION_CONFIG_LOCK_Msk ),
264- "i" (RRAMC_REGION_CONFIG_SIZE_Msk )
265- #endif /* CONFIG_SB_DISABLE_SELF_RWX */
266- : "r0" , "r1" , "r2" , "r3" , "r4" , "r5" , "memory"
267- );
304+ jump_in ((vector_table [1 ]));
268305
269306 CODE_UNREACHABLE ;
270307}
0 commit comments