19
19
#include <hal/nrf_gpio.h>
20
20
#endif
21
21
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
+
22
67
#if defined(CONFIG_SB_DISABLE_SELF_RWX )
23
68
/* Disabling R_X has to be done while running from RAM for obvious reasons.
24
69
* 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.
29
72
*/
30
73
#include <hal/nrf_rramc.h>
31
74
32
- #define FUNCTION_BUFFER_LEN 64
33
75
#define RRAMC_REGION_RWX_LSB 0
34
76
#define RRAMC_REGION_RWX_WIDTH 3
35
77
#define RRAMC_REGION_TO_LOCK_ADDR NRF_RRAMC->REGION[3].CONFIG
36
78
#define RRAMC_REGION_TO_LOCK_ADDR_H (((uint32_t)(&(RRAMC_REGION_TO_LOCK_ADDR))) >> 16)
37
79
#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 ];
39
80
#endif /* CONFIG_SB_DISABLE_SELF_RWX */
40
81
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
+
41
160
#ifdef CONFIG_UART_NRFX_UARTE
42
161
static void uninit_used_uarte (NRF_UARTE_Type * p_reg )
43
162
{
@@ -163,6 +282,13 @@ void bl_boot(const struct fw_info *fw_info)
163
282
VTOR = fw_info -> address ;
164
283
uint32_t * vector_table = (uint32_t * )fw_info -> address ;
165
284
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
+
166
292
#if defined(CONFIG_BUILTIN_STACK_GUARD ) && \
167
293
defined(CONFIG_CPU_CORTEX_M_HAS_SPLIM )
168
294
/* Reset limit registers to avoid inflicting stack overflow on image
@@ -175,96 +301,7 @@ void bl_boot(const struct fw_info *fw_info)
175
301
__set_MSP (vector_table [0 ]);
176
302
__set_PSP (0 );
177
303
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 ]));
268
305
269
306
CODE_UNREACHABLE ;
270
307
}
0 commit comments