diff --git a/subsys/bootloader/Kconfig b/subsys/bootloader/Kconfig index 09255c4eee31..05d139727fbd 100644 --- a/subsys/bootloader/Kconfig +++ b/subsys/bootloader/Kconfig @@ -103,6 +103,12 @@ config SB_CLEANUP_RAM help Sets contents of memory to 0 before jumping to application. +config SB_DISABLE_SELF_R_X + bool "Disable read and execution on self NVM" + depends on SOC_NRF54L15_CPUAPP && !FPROTECT_ALLOW_COMBINED_REGIONS + help + Sets RRAMC's BOOTCONF region protection before jumping to application. + endif # IS_SECURE_BOOTLOADER config IS_BOOTLOADER_IMG diff --git a/subsys/bootloader/bl_boot/bl_boot.c b/subsys/bootloader/bl_boot/bl_boot.c index a70a92e10dd3..61355626fbee 100644 --- a/subsys/bootloader/bl_boot/bl_boot.c +++ b/subsys/bootloader/bl_boot/bl_boot.c @@ -19,6 +19,54 @@ #include #endif +/* Disabling R_X has to be done while running from RAM for obvious reasons. + * Moreover as a last step before jumping to application it must work even after + * RAW has been cleared, therefore we are using custom RAM function relocator. + * Size of the relocated are isn't known but it doesn't matter as long as it contains at least + * entire aforementioned function. + */ +#define FUNCTION_BUFFER_LEN 128 +#define RRAMC_REGION_TO_LOCK_ADDR 0x5004b56c +#define RRAMC_REGION_TO_LOCK_ADDR_H (RRAMC_REGION_TO_LOCK_ADDR >> 16) +#define RRAMC_REGION_TO_LOCK_ADDR_L (RRAMC_REGION_TO_LOCK_ADDR & 0x0000fffful) +typedef void (*ram_fn_ptr)(uint32_t); +uint8_t ram_exec_buf[FUNCTION_BUFFER_LEN]; + +static void bootconf_disable_r_x_and_jump(uint32_t vector) +{ + __asm__ volatile ( + " MOV r5, %0\n" + " MOV r1, %1\n" + " MOVT r1, %2\n" + " LDR r0, [r1]\n" + /* Size of the region should be set at this point + * by provisioning through BOOTCONF. If not set it according partition size. + */ + " RORS r4, r0, #16\n" + " CBNZ r4, clear_rwx\n" + " MOVT r0, %3\n" + "clear_rwx:\n" + " BFC r0, #0, #3\n" + " STR r0, [r1]\n" + " DSB\n" + " BX r5\n" + : + : "r" (vector), "i" (RRAMC_REGION_TO_LOCK_ADDR_L), + "i" (RRAMC_REGION_TO_LOCK_ADDR_H), "i" (CONFIG_PM_PARTITION_SIZE_B0_IMAGE / 1024) + : "r0", "r1", "r2", "r4", "r5", "memory" + ); +} + +static ram_fn_ptr relocate_bootconf_disable_r_x_and_jump(void) +{ + uint32_t *adjusted_addr = + (uint32_t *)((uint32_t)bootconf_disable_r_x_and_jump & 0xfffffffeul); + memcpy(ram_exec_buf, adjusted_addr, FUNCTION_BUFFER_LEN); + ram_fn_ptr call_ptr = (ram_fn_ptr)((uint32_t)ram_exec_buf | 0x00000001ul); + return call_ptr; +} + + #ifdef CONFIG_UART_NRFX_UARTE static void uninit_used_uarte(NRF_UARTE_Type *p_reg) { @@ -174,13 +222,18 @@ void bl_boot(const struct fw_info *fw_info) " b clear\n" "out:\n" " dsb\n" +#ifndef CONFIG_SB_DISABLE_SELF_R_X /* Jump to reset vector of an app */ " bx r0\n" +#endif : : "r" (vector_table[1]), "i" (CONFIG_SRAM_BASE_ADDRESS), "i" (CONFIG_SRAM_SIZE * 1024), "i" (0) : "r0", "r1", "r2", "r3", "memory" ); +#elif defined(CONFIG_SB_DISABLE_SELF_R_X) + + relocate_bootconf_disable_r_x_and_jump()(vector_table[1]); #else /* Call reset handler. */ ((void (*)(void))vector_table[1])();