aboutsummaryrefslogtreecommitdiff
path: root/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/bootloader/nrf_bootloader_app_start_final.c
diff options
context:
space:
mode:
Diffstat (limited to 'thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/bootloader/nrf_bootloader_app_start_final.c')
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/bootloader/nrf_bootloader_app_start_final.c256
1 files changed, 256 insertions, 0 deletions
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/bootloader/nrf_bootloader_app_start_final.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/bootloader/nrf_bootloader_app_start_final.c
new file mode 100644
index 0000000..a818322
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/bootloader/nrf_bootloader_app_start_final.c
@@ -0,0 +1,256 @@
+/**
+ * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#include "sdk_config.h"
+#include "nrf_bootloader_app_start.h"
+#include <stdint.h>
+#include "nrf.h"
+#include "nrf_peripherals.h"
+#include "nrf_bootloader_info.h"
+#include "nrf_dfu_types.h"
+#include "nrf_assert.h"
+#include "nrf_log.h"
+#include "sdk_config.h"
+
+
+// Enabling the NRF_BOOTLOADER_READ_PROTECT define is untested.
+// Read-protecting the bootloader requires certain functions to run from RAM.
+// In GCC and SES this is done automatically when the define is enabled. You will
+// get warnings which can be ignored.
+// In Keil you must change project settings to run the entire file from RAM.
+#ifndef NRF_BOOTLOADER_READ_PROTECT
+#define NRF_BOOTLOADER_READ_PROTECT 0
+#endif
+
+
+#define HANDLER_MODE_EXIT 0xFFFFFFF9 // When this is jumped to, the CPU will exit interrupt context
+ // (handler mode), and pop values from the stack into registers.
+ // See ARM's documentation for "Exception entry and return".
+#define EXCEPTION_STACK_WORD_COUNT 8 // The number of words popped from the stack when
+ // HANDLER_MODE_EXIT is branched to.
+
+
+/**@brief Function that sets the stack pointer and link register, and starts executing a particular address.
+ *
+ * @param[in] new_msp The new value to set in the main stack pointer.
+ * @param[in] new_lr The new value to set in the link register.
+ * @param[in] addr The address to execute.
+ */
+#if defined ( __CC_ARM )
+__ASM __STATIC_INLINE void jump_to_addr(uint32_t new_msp, uint32_t new_lr, uint32_t addr)
+{
+ MSR MSP, R0;
+ MOV LR, R1;
+ BX R2;
+}
+#else
+__STATIC_INLINE void jump_to_addr(uint32_t new_msp, uint32_t new_lr, uint32_t addr)
+{
+ __ASM volatile ("MSR MSP, %[arg]" : : [arg] "r" (new_msp));
+ __ASM volatile ("MOV LR, %[arg]" : : [arg] "r" (new_lr) : "lr");
+ __ASM volatile ("BX %[arg]" : : [arg] "r" (addr));
+}
+#endif
+
+
+/**@brief Function for booting an app as if the chip was reset.
+ *
+ * @param[in] vector_table_addr The address of the app's vector table.
+ */
+__STATIC_INLINE void app_start(uint32_t vector_table_addr)
+{
+ const uint32_t current_isr_num = (__get_IPSR() & IPSR_ISR_Msk);
+ const uint32_t new_msp = *((uint32_t *)(vector_table_addr)); // The app's Stack Pointer is found as the first word of the vector table.
+ const uint32_t reset_handler = *((uint32_t *)(vector_table_addr + sizeof(uint32_t))); // The app's Reset Handler is found as the second word of the vector table.
+ const uint32_t new_lr = 0xFFFFFFFF;
+
+ __set_CONTROL(0x00000000); // Set CONTROL to its reset value 0.
+ __set_PRIMASK(0x00000000); // Set PRIMASK to its reset value 0.
+ __set_BASEPRI(0x00000000); // Set BASEPRI to its reset value 0.
+ __set_FAULTMASK(0x00000000); // Set FAULTMASK to its reset value 0.
+
+ if (current_isr_num == 0)
+ {
+ // The CPU is in Thread mode (main context).
+ jump_to_addr(new_msp, new_lr, reset_handler); // Jump directly to the App's Reset Handler.
+ }
+ else
+ {
+ // The CPU is in Handler mode (interrupt context).
+
+ const uint32_t exception_stack[EXCEPTION_STACK_WORD_COUNT] = // To be copied onto the stack.
+ {
+ 0x00000000, // New value of R0. Cleared by setting to 0.
+ 0x00000000, // New value of R1. Cleared by setting to 0.
+ 0x00000000, // New value of R2. Cleared by setting to 0.
+ 0x00000000, // New value of R3. Cleared by setting to 0.
+ 0x00000000, // New value of R12. Cleared by setting to 0.
+ 0xFFFFFFFF, // New value of LR. Cleared by setting to all 1s.
+ reset_handler, // New value of PC. The CPU will continue by executing the App's Reset Handler.
+ xPSR_T_Msk, // New value of xPSR (Thumb mode set).
+ };
+ const uint32_t exception_sp = new_msp - sizeof(exception_stack);
+
+ memcpy((uint32_t *)exception_sp, exception_stack, sizeof(exception_stack)); // 'Push' exception_stack onto the App's stack.
+
+ jump_to_addr(exception_sp, new_lr, HANDLER_MODE_EXIT); // 'Jump' to the special value to exit handler mode. new_lr is superfluous here.
+ // exception_stack will be popped from the stack, so the resulting SP will be the new_msp.
+ // Execution will continue from the App's Reset Handler.
+ }
+}
+
+#if NRF_BOOTLOADER_READ_PROTECT
+#ifdef __ICCARM__
+__ramfunc
+#elif defined ( __GNUC__ ) || defined ( __SES_ARM )
+__attribute__((noinline, long_call, section(".data")))
+#elif defined ( __CC_ARM )
+#warning "Keil requires changes to project settings to run this file from RAM. Ignore this warning if configuration has been made."
+#endif
+#endif
+ret_code_t nrf_bootloader_flash_protect(uint32_t address, uint32_t size, bool read_protect)
+{
+ if ((size & (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;
+
+ uint32_t const wmask = (ACL_ACL_PERM_WRITE_Disable << ACL_ACL_PERM_WRITE_Pos);
+ uint32_t const rwmask = wmask | (ACL_ACL_PERM_READ_Disable << ACL_ACL_PERM_READ_Pos);
+ uint32_t const mask = read_protect ? rwmask: wmask;
+
+ do
+ {
+ if (acl_instance >= ACL_REGIONS_COUNT)
+ {
+ return NRF_ERROR_NO_MEM;
+ }
+
+ NRF_ACL->ACL[acl_instance].ADDR = address;
+ NRF_ACL->ACL[acl_instance].SIZE = size;
+ NRF_ACL->ACL[acl_instance].PERM = mask;
+
+ acl_instance++;
+
+ } while (NRF_ACL->ACL[acl_instance - 1].ADDR != address
+ || NRF_ACL->ACL[acl_instance - 1].SIZE != size
+ || NRF_ACL->ACL[acl_instance - 1].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;
+ case 2:
+ NRF_BPROT->CONFIG2 = mask;
+ break;
+ case 3:
+ NRF_BPROT->CONFIG3 = mask;
+ break;
+ }
+ }
+
+#endif
+
+ return NRF_SUCCESS;
+}
+
+
+#if NRF_BOOTLOADER_READ_PROTECT
+#ifdef __ICCARM__
+__ramfunc
+#elif defined ( __GNUC__ ) || defined ( __SES_ARM )
+__attribute__((noinline, long_call, section(".data")))
+#elif defined ( __CC_ARM )
+#warning "Keil requires changes to project settings to run this file from RAM. Ignore this warning if configuration has been made."
+#endif
+#endif
+void nrf_bootloader_app_start_final(uint32_t vector_table_addr)
+{
+ ret_code_t ret_val;
+
+ // Protect MBR & bootloader code and params pages.
+ if (NRF_BOOTLOADER_READ_PROTECT)
+ {
+ ret_val = nrf_bootloader_flash_protect(0, MBR_SIZE, NRF_BOOTLOADER_READ_PROTECT);
+ }
+
+ // Size of the flash area to protect.
+ uint32_t area_size;
+
+ if (!NRF_BL_SETTINGS_PAGE_PROTECT)
+ {
+ area_size = BOOTLOADER_SIZE + NRF_MBR_PARAMS_PAGE_SIZE;
+ }
+ else
+ {
+ area_size = BOOTLOADER_SIZE + NRF_MBR_PARAMS_PAGE_SIZE + BOOTLOADER_SETTINGS_PAGE_SIZE;
+ }
+
+ ret_val = nrf_bootloader_flash_protect(BOOTLOADER_START_ADDR,
+ area_size,
+ NRF_BOOTLOADER_READ_PROTECT);
+
+ if (!NRF_BOOTLOADER_READ_PROTECT && (ret_val != NRF_SUCCESS))
+ {
+ NRF_LOG_ERROR("Could not protect bootloader and settings pages, 0x%x.", ret_val);
+ }
+
+ // Run application
+ app_start(vector_table_addr);
+}