diff --git a/lib/sdk11/components/libraries/bootloader_dfu/bootloader_util.c b/lib/sdk11/components/libraries/bootloader_dfu/bootloader_util.c index 62cb2856..a1fb9be3 100644 --- a/lib/sdk11/components/libraries/bootloader_dfu/bootloader_util.c +++ b/lib/sdk11/components/libraries/bootloader_dfu/bootloader_util.c @@ -11,10 +11,13 @@ */ #include "bootloader_util.h" +#include "dfu_types.h" +#include "nrf_peripherals.h" + #include +#include #include - /** * @brief Function for aborting current application/bootloader jump to to other app/bootloader. * @@ -164,8 +167,76 @@ static inline void bootloader_util_reset(uint32_t start_addr) #error Compiler not supported. #endif +// protect flash region from write access +static uint32_t bootloader_util_flash_protect(uint32_t address, uint32_t size) { + if ((size & (CODE_PAGE_SIZE - 1)) || (address & (CODE_PAGE_SIZE - 1)) || (address > BOOTLOADER_SETTINGS_ADDRESS)) { + return NRF_ERROR_INVALID_PARAM; + } + +#if defined(ACL_PRESENT) + // Protect using ACL. + static uint32_t acl_instance = 0; + + volatile ACL_ACL_Type *p_acl; + const uint32_t mask = (ACL_ACL_PERM_WRITE_Disable << ACL_ACL_PERM_WRITE_Pos); + + do { + if (acl_instance >= ACL_REGIONS_COUNT) { + return NRF_ERROR_NO_MEM; + } + + p_acl = &NRF_ACL->ACL[acl_instance]; + p_acl->ADDR = address; + p_acl->SIZE = size; + p_acl->PERM = mask; + + acl_instance++; + + } while (p_acl->ADDR != address || p_acl->SIZE != size || + p_acl->PERM != mask); // Check whether the acl_instance has been used before. + +#elif defined(BPROT_PRESENT) + // Protect using BPROT. BPROT does not support read protection. + uint32_t pagenum_start = address / CODE_PAGE_SIZE; + uint32_t pagenum_end = pagenum_start + ((size - 1) / CODE_PAGE_SIZE); + + for (uint32_t i = pagenum_start; i <= pagenum_end; i++) { + uint32_t config_index = i / 32; + uint32_t mask = (1 << (i - config_index * 32)); + + switch (config_index) { + case 0: + NRF_BPROT->CONFIG0 = mask; + break; + case 1: + NRF_BPROT->CONFIG1 = mask; + break; + #if BPROT_REGIONS_NUM > 64 + case 2: + NRF_BPROT->CONFIG2 = mask; + break; + case 3: + NRF_BPROT->CONFIG3 = mask; + break; + #endif + } + } -void bootloader_util_app_start(uint32_t start_addr) -{ - bootloader_util_reset(start_addr); +#endif + + return NRF_SUCCESS; +} + +void bootloader_util_app_start(uint32_t start_addr) { + // Protect MBR against user writes + bootloader_util_flash_protect(0, MBR_SIZE); + + // Size of the bootloader flash area to protect (Bootloader + MBR params + Bootloader settings) + const uint32_t area_size = BOOTLOADER_SETTINGS_ADDRESS + CODE_PAGE_SIZE - BOOTLOADER_REGION_START; + + // Protect bootloader code and params pages against user writes + bootloader_util_flash_protect(BOOTLOADER_REGION_START, area_size); + + // Jump to user application + bootloader_util_reset(start_addr); } diff --git a/lib/sdk11/components/libraries/bootloader_dfu/dfu_types.h b/lib/sdk11/components/libraries/bootloader_dfu/dfu_types.h index e186e055..665f9c48 100644 --- a/lib/sdk11/components/libraries/bootloader_dfu/dfu_types.h +++ b/lib/sdk11/components/libraries/bootloader_dfu/dfu_types.h @@ -20,6 +20,37 @@ * @brief Device Firmware Update module type and definitions. */ +/* + * Flash layout (nrf52840, see linker/nrf52840.ld): + * + * ------------------------- + * | Bootloader Settings | + * | 4 KB | + * |-------------------------| 0xFF000 BOOTLOADER_SETTINGS_ADDRESS + * | MBR Params Page | + * | 4 KB | + * |-------------------------| 0xFE000 + * | Bootloader Config | + * | 2 KB | + * |-------------------------| 0xFD800 + * | Bootloader | + * | 38 KB | + * |-------------------------| 0xF4000 BOOTLOADER_REGION_START + * | App Data Reserved | + * | 40 KB | + * |-------------------------| 0xEA000 + * | Application | + * | Single/ Dual Bank | + * | | + * |-------------------------| CODE_REGION_1_START + * | SoftDevice | + * | 0x26000 (optional) | + * |-------------------------| 0x01000 + * | MBR | + * | 4 KB | + * ------------------------- 0x00000 + */ + #ifndef DFU_TYPES_H__ #define DFU_TYPES_H__