Skip to content

Commit

Permalink
bootloader: self lock at the end of execution
Browse files Browse the repository at this point in the history
Disables read and execute on memory containing NSIB
right before jumping to application.

Signed-off-by: Mateusz Michalek <[email protected]>
  • Loading branch information
michalek-no committed Jan 30, 2025
1 parent 436fd2f commit cf1c54a
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 0 deletions.
6 changes: 6 additions & 0 deletions subsys/bootloader/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
53 changes: 53 additions & 0 deletions subsys/bootloader/bl_boot/bl_boot.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,54 @@
#include <hal/nrf_gpio.h>
#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)
{
Expand Down Expand Up @@ -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])();
Expand Down

0 comments on commit cf1c54a

Please sign in to comment.