|
1 | 1 | /*
|
2 |
| - * Copyright (c) 2020 Nordic Semiconductor ASA |
| 2 | + * Copyright (c) 2020-2025 Nordic Semiconductor ASA |
3 | 3 | *
|
4 | 4 | * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
|
5 | 5 | */
|
|
19 | 19 | #include <hal/nrf_gpio.h>
|
20 | 20 | #endif
|
21 | 21 |
|
| 22 | +#if defined(CONFIG_SB_DISABLE_SELF_RWX) |
| 23 | +/* Disabling R_X has to be done while running from RAM for obvious reasons. |
| 24 | + * 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. |
| 29 | + */ |
| 30 | +#include <hal/nrf_rramc.h> |
| 31 | + |
| 32 | +#define FUNCTION_BUFFER_LEN 64 |
| 33 | +#define RRAMC_REGION_RWX_LSB 0 |
| 34 | +#define RRAMC_REGION_RWX_WIDTH 3 |
| 35 | +#define RRAMC_REGION_TO_LOCK_ADDR NRF_RRAMC->REGION[3].CONFIG |
| 36 | +#define RRAMC_REGION_TO_LOCK_ADDR_H (((uint32_t)(&(RRAMC_REGION_TO_LOCK_ADDR))) >> 16) |
| 37 | +#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 | +#endif /* CONFIG_SB_DISABLE_SELF_RWX */ |
| 40 | + |
22 | 41 | #ifdef CONFIG_UART_NRFX_UARTE
|
23 | 42 | static void uninit_used_uarte(NRF_UARTE_Type *p_reg)
|
24 | 43 | {
|
@@ -151,39 +170,100 @@ void bl_boot(const struct fw_info *fw_info)
|
151 | 170 | __set_PSPLIM(0);
|
152 | 171 | __set_MSPLIM(0);
|
153 | 172 | #endif
|
154 |
| - |
155 | 173 | /* Set MSP to the new address and clear any information from PSP */
|
156 | 174 | __set_MSP(vector_table[0]);
|
157 | 175 | __set_PSP(0);
|
158 | 176 |
|
159 |
| -#if CONFIG_SB_CLEANUP_RAM |
160 | 177 | __asm__ volatile (
|
161 | 178 | /* vector_table[1] -> r0 */
|
162 |
| - " mov r0, %0\n" |
| 179 | + " mov r0, %0\n" |
| 180 | +#ifdef CONFIG_SB_CLEANUP_RAM |
163 | 181 | /* Base to write -> r1 */
|
164 |
| - " mov r1, %1\n" |
| 182 | + " mov r1, %1\n" |
165 | 183 | /* Size to write -> r2 */
|
166 |
| - " mov r2, %2\n" |
| 184 | + " mov r2, %2\n" |
167 | 185 | /* Value to write -> r3 */
|
168 |
| - " mov r3, %3\n" |
| 186 | + " movw r3, %3\n" |
169 | 187 | "clear:\n"
|
170 |
| - " str r3, [r1]\n" |
171 |
| - " add r1, r1, #4\n" |
172 |
| - " sub r2, r2, #4\n" |
173 |
| - " cbz r2, out\n" |
174 |
| - " b clear\n" |
| 188 | + " str r3, [r1]\n" |
| 189 | + " add r1, r1, #4\n" |
| 190 | + " sub r2, r2, #4\n" |
| 191 | + " cbz r2, out\n" |
| 192 | + " b clear\n" |
175 | 193 | "out:\n"
|
176 | 194 | " dsb\n"
|
| 195 | +#endif /* CONFIG_SB_CLEANUP_RAM */ |
| 196 | + |
| 197 | +#ifdef CONFIG_SB_DISABLE_SELF_RWX |
| 198 | + /* FUNCTION_BUFFER_LEN */ |
| 199 | + " movw r4, %4\n" |
| 200 | + /* Address of ram_exec_buf goes to r2 */ |
| 201 | + " mov r2, %5\n" |
| 202 | + " movw r3, :lower16:bootconf_disable_rwx\n" |
| 203 | + " movt r3, :upper16:bootconf_disable_rwx\n" |
| 204 | + /* Adjust address for thumb */ |
| 205 | + " and r3, #0xfffffffe\n" |
| 206 | + /* Address of ram_exec_buf also goes to r5 */ |
| 207 | + " mov r5, %5\n" |
| 208 | + /* Adjust buffer address for thumb */ |
| 209 | + " orr r5, #0x1\n" |
| 210 | + /* End of the copy address in r4 */ |
| 211 | + " add r4, r2\n" |
| 212 | + "ram_cpy:\n" |
| 213 | + /* Read and increment */ |
| 214 | + " ldrb r1, [r3], #1\n" |
| 215 | + /* Write and increment */ |
| 216 | + " strb r1, [r2], #1\n" |
| 217 | + /* Check if end address is reached */ |
| 218 | + " cmp r2, r4\n" |
| 219 | + " bne ram_cpy\n" |
| 220 | + " dsb\n" |
| 221 | + /* Jump to ram */ |
| 222 | + " bx r5\n" |
| 223 | + /* CODE_UNREACHABLE */ |
| 224 | + |
| 225 | + ".thumb_func\n" |
| 226 | + "bootconf_disable_rwx:\n" |
| 227 | + " movw r1, %6\n" |
| 228 | + " movt r1, %7\n" |
| 229 | + " ldr r2, [r1]\n" |
| 230 | + /* Size of the region should be set at this point |
| 231 | + * by provisioning through BOOTCONF. |
| 232 | + * If not, set it according partition size. |
| 233 | + */ |
| 234 | + " ands r4, r2, %12\n" |
| 235 | + " cbnz r4, clear_rwx\n" |
| 236 | + " movt r2, %8\n" |
| 237 | + "clear_rwx:\n" |
| 238 | + " bfc r2, %9, %10\n" |
| 239 | + /* Disallow further modifications */ |
| 240 | + " orr r2, %11\n" |
| 241 | + " str r2, [r1]\n" |
| 242 | + " dsb\n" |
| 243 | + /* Next assembly line is important for current function */ |
| 244 | + |
| 245 | +#endif /* CONFIG_SB_DISABLE_SELF_RWX */ |
| 246 | + |
177 | 247 | /* Jump to reset vector of an app */
|
178 |
| - " bx r0\n" |
| 248 | + " bx r0\n" |
179 | 249 | :
|
180 |
| - : "r" (vector_table[1]), "i" (CONFIG_SRAM_BASE_ADDRESS), |
181 |
| - "i" (CONFIG_SRAM_SIZE * 1024), "i" (0) |
182 |
| - : "r0", "r1", "r2", "r3", "memory" |
| 250 | + : "r" (vector_table[1]), |
| 251 | + "i" (CONFIG_SRAM_BASE_ADDRESS), |
| 252 | + "i" (CONFIG_SRAM_SIZE * 1024), |
| 253 | + "i" (0) |
| 254 | +#ifdef CONFIG_SB_DISABLE_SELF_RWX |
| 255 | + , "i" (FUNCTION_BUFFER_LEN), |
| 256 | + "r" (ram_exec_buf), |
| 257 | + "i" (RRAMC_REGION_TO_LOCK_ADDR_L), |
| 258 | + "i" (RRAMC_REGION_TO_LOCK_ADDR_H), |
| 259 | + "i" (CONFIG_PM_PARTITION_SIZE_B0_IMAGE / 1024), |
| 260 | + "i" (RRAMC_REGION_RWX_LSB), |
| 261 | + "i" (RRAMC_REGION_RWX_WIDTH), |
| 262 | + "i" (RRAMC_REGION_CONFIG_LOCK_Msk), |
| 263 | + "i" (RRAMC_REGION_CONFIG_SIZE_Msk) |
| 264 | +#endif /* CONFIG_SB_DISABLE_SELF_RWX */ |
| 265 | + : "r0", "r1", "r2", "r3", "r4", "r5", "memory" |
183 | 266 | );
|
184 |
| -#else |
185 |
| - /* Call reset handler. */ |
186 |
| - ((void (*)(void))vector_table[1])(); |
187 |
| -#endif |
| 267 | + |
188 | 268 | CODE_UNREACHABLE;
|
189 | 269 | }
|
0 commit comments