nrf_bootloader.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567
  1. /**
  2. * Copyright (c) 2016 - 2020, Nordic Semiconductor ASA
  3. *
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without modification,
  7. * are permitted provided that the following conditions are met:
  8. *
  9. * 1. Redistributions of source code must retain the above copyright notice, this
  10. * list of conditions and the following disclaimer.
  11. *
  12. * 2. Redistributions in binary form, except as embedded into a Nordic
  13. * Semiconductor ASA integrated circuit in a product or a software update for
  14. * such product, must reproduce the above copyright notice, this list of
  15. * conditions and the following disclaimer in the documentation and/or other
  16. * materials provided with the distribution.
  17. *
  18. * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
  19. * contributors may be used to endorse or promote products derived from this
  20. * software without specific prior written permission.
  21. *
  22. * 4. This software, with or without modification, must only be used with a
  23. * Nordic Semiconductor ASA integrated circuit.
  24. *
  25. * 5. Any software provided in binary form under this license must not be reverse
  26. * engineered, decompiled, modified and/or disassembled.
  27. *
  28. * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
  29. * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  30. * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
  31. * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
  32. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  33. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
  34. * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  35. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  36. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  37. * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  38. *
  39. */
  40. #include "nrf_bootloader.h"
  41. #include "compiler_abstraction.h"
  42. #include "nrf.h"
  43. #include "boards.h"
  44. #include "sdk_config.h"
  45. #include "nrf_power.h"
  46. #include "nrf_delay.h"
  47. #include "nrf_log.h"
  48. #include "nrf_log_ctrl.h"
  49. #include "nrf_dfu.h"
  50. #include "nrf_error.h"
  51. #include "nrf_dfu_settings.h"
  52. #include "nrf_dfu_utils.h"
  53. #include "nrf_bootloader_wdt.h"
  54. #include "nrf_bootloader_info.h"
  55. #include "nrf_bootloader_app_start.h"
  56. #include "nrf_bootloader_fw_activation.h"
  57. #include "nrf_bootloader_dfu_timers.h"
  58. #include "app_scheduler.h"
  59. #include "nrf_dfu_validation.h"
  60. #include "nrf_sdh.h"
  61. static nrf_dfu_observer_t m_user_observer; //<! Observer callback set by the user.
  62. static volatile bool m_flash_write_done;
  63. #define SCHED_QUEUE_SIZE 32 /**< Maximum number of events in the scheduler queue. */
  64. #define SCHED_EVENT_DATA_SIZE NRF_DFU_SCHED_EVENT_DATA_SIZE /**< Maximum app_scheduler event size. */
  65. #if !(defined(NRF_BL_DFU_ENTER_METHOD_BUTTON) && \
  66. defined(NRF_BL_DFU_ENTER_METHOD_PINRESET) && \
  67. defined(NRF_BL_DFU_ENTER_METHOD_GPREGRET) && \
  68. defined(NRF_BL_DFU_ENTER_METHOD_BUTTONLESS)&& \
  69. defined(NRF_BL_RESET_DELAY_MS) && \
  70. defined(NRF_BL_DEBUG_PORT_DISABLE))
  71. #error Configuration file is missing flags. Update sdk_config.h.
  72. #endif
  73. STATIC_ASSERT((NRF_BL_DFU_INACTIVITY_TIMEOUT_MS >= 100) || (NRF_BL_DFU_INACTIVITY_TIMEOUT_MS == 0),
  74. "NRF_BL_DFU_INACTIVITY_TIMEOUT_MS must be 100 ms or more, or 0 to indicate that it is disabled.");
  75. #if defined(NRF_LOG_BACKEND_FLASH_START_PAGE)
  76. STATIC_ASSERT(NRF_LOG_BACKEND_FLASH_START_PAGE != 0,
  77. "If nrf_log flash backend is used it cannot use space after code because it would collide with settings page.");
  78. #endif
  79. /**@brief Weak implemenation of nrf_dfu_init
  80. *
  81. * @note This function will be overridden if nrf_dfu.c is
  82. * compiled and linked with the project
  83. */
  84. #if (__LINT__ != 1)
  85. __WEAK uint32_t nrf_dfu_init(nrf_dfu_observer_t observer)
  86. {
  87. NRF_LOG_DEBUG("in weak nrf_dfu_init");
  88. return NRF_SUCCESS;
  89. }
  90. #endif
  91. /**@brief Weak implementation of nrf_dfu_init
  92. *
  93. * @note This function must be overridden in application if
  94. * user-specific initialization is needed.
  95. */
  96. __WEAK uint32_t nrf_dfu_init_user(void)
  97. {
  98. NRF_LOG_DEBUG("in weak nrf_dfu_init_user");
  99. return NRF_SUCCESS;
  100. }
  101. static void flash_write_callback(void * p_context)
  102. {
  103. UNUSED_PARAMETER(p_context);
  104. m_flash_write_done = true;
  105. }
  106. static void do_reset(void * p_context)
  107. {
  108. UNUSED_PARAMETER(p_context);
  109. NRF_LOG_FINAL_FLUSH();
  110. nrf_delay_ms(NRF_BL_RESET_DELAY_MS);
  111. NVIC_SystemReset();
  112. }
  113. static void bootloader_reset(bool do_backup)
  114. {
  115. NRF_LOG_DEBUG("Resetting bootloader.");
  116. if (do_backup)
  117. {
  118. m_flash_write_done = false;
  119. nrf_dfu_settings_backup(do_reset);
  120. }
  121. else
  122. {
  123. do_reset(NULL);
  124. }
  125. }
  126. static void inactivity_timeout(void)
  127. {
  128. NRF_LOG_INFO("Inactivity timeout.");
  129. bootloader_reset(true);
  130. }
  131. /**@brief Function for handling DFU events.
  132. */
  133. static void dfu_observer(nrf_dfu_evt_type_t evt_type)
  134. {
  135. switch (evt_type)
  136. {
  137. case NRF_DFU_EVT_DFU_STARTED:
  138. case NRF_DFU_EVT_OBJECT_RECEIVED:
  139. nrf_bootloader_dfu_inactivity_timer_restart(
  140. NRF_BOOTLOADER_MS_TO_TICKS(NRF_BL_DFU_INACTIVITY_TIMEOUT_MS),
  141. inactivity_timeout);
  142. break;
  143. case NRF_DFU_EVT_DFU_COMPLETED:
  144. case NRF_DFU_EVT_DFU_ABORTED:
  145. bootloader_reset(true);
  146. break;
  147. case NRF_DFU_EVT_TRANSPORT_DEACTIVATED:
  148. // Reset the internal state of the DFU settings to the last stored state.
  149. nrf_dfu_settings_reinit();
  150. break;
  151. default:
  152. break;
  153. }
  154. if (m_user_observer)
  155. {
  156. m_user_observer(evt_type);
  157. }
  158. }
  159. /**@brief Function for initializing the event scheduler.
  160. */
  161. static void scheduler_init(void)
  162. {
  163. APP_SCHED_INIT(SCHED_EVENT_DATA_SIZE, SCHED_QUEUE_SIZE);
  164. }
  165. /**@brief Suspend the CPU until an interrupt occurs.
  166. */
  167. static void wait_for_event(void)
  168. {
  169. #if defined(BLE_STACK_SUPPORT_REQD) || defined(ANT_STACK_SUPPORT_REQD)
  170. (void)sd_app_evt_wait();
  171. #else
  172. // Wait for an event.
  173. __WFE();
  174. // Clear the internal event register.
  175. __SEV();
  176. __WFE();
  177. #endif
  178. }
  179. /**@brief Continually sleep and process tasks whenever woken.
  180. */
  181. static void loop_forever(void)
  182. {
  183. while (true)
  184. {
  185. //feed the watchdog if enabled.
  186. nrf_bootloader_wdt_feed();
  187. app_sched_execute();
  188. if (!NRF_LOG_PROCESS())
  189. {
  190. wait_for_event();
  191. }
  192. }
  193. }
  194. #if NRF_BL_DFU_ENTER_METHOD_BUTTON
  195. #ifndef BUTTON_PULL
  196. #error NRF_BL_DFU_ENTER_METHOD_BUTTON is enabled but not buttons seem to be available on the board.
  197. #endif
  198. /**@brief Function for initializing button used to enter DFU mode.
  199. */
  200. static void dfu_enter_button_init(void)
  201. {
  202. nrf_gpio_cfg_sense_input(NRF_BL_DFU_ENTER_METHOD_BUTTON_PIN,
  203. BUTTON_PULL,
  204. NRF_GPIO_PIN_SENSE_LOW);
  205. }
  206. #endif
  207. static bool crc_on_valid_app_required(void)
  208. {
  209. bool ret = true;
  210. if (NRF_BL_APP_CRC_CHECK_SKIPPED_ON_SYSTEMOFF_RESET &&
  211. (nrf_power_resetreas_get() & NRF_POWER_RESETREAS_OFF_MASK))
  212. {
  213. nrf_power_resetreas_clear(NRF_POWER_RESETREAS_OFF_MASK);
  214. ret = false;
  215. }
  216. else if (NRF_BL_APP_CRC_CHECK_SKIPPED_ON_GPREGRET2 &&
  217. ((nrf_power_gpregret2_get() & BOOTLOADER_DFU_GPREGRET2_MASK) == BOOTLOADER_DFU_GPREGRET2)
  218. && (nrf_power_gpregret2_get() & BOOTLOADER_DFU_SKIP_CRC_BIT_MASK))
  219. {
  220. nrf_power_gpregret2_set(nrf_power_gpregret2_get() & ~BOOTLOADER_DFU_SKIP_CRC);
  221. ret = false;
  222. }
  223. else
  224. {
  225. }
  226. return ret;
  227. }
  228. static bool boot_validate(boot_validation_t const * p_validation, uint32_t data_addr, uint32_t data_len, bool do_crc)
  229. {
  230. if (!do_crc && (p_validation->type == VALIDATE_CRC))
  231. {
  232. return true;
  233. }
  234. return nrf_dfu_validation_boot_validate(p_validation, data_addr, data_len);
  235. }
  236. /** @brief Function for checking if the main application is valid.
  237. *
  238. * @details This function checks if there is a valid application
  239. * located at Bank 0.
  240. *
  241. * @param[in] do_crc Perform CRC check on application. Only CRC checks
  242. can be skipped. For other boot validation types,
  243. this parameter is ignored.
  244. *
  245. * @retval true If a valid application has been detected.
  246. * @retval false If there is no valid application.
  247. */
  248. static bool app_is_valid(bool do_crc)
  249. {
  250. if (s_dfu_settings.bank_0.bank_code != NRF_DFU_BANK_VALID_APP)
  251. {
  252. NRF_LOG_INFO("Boot validation failed. No valid app to boot.");
  253. return false;
  254. }
  255. else if (NRF_BL_APP_SIGNATURE_CHECK_REQUIRED &&
  256. (s_dfu_settings.boot_validation_app.type != VALIDATE_ECDSA_P256_SHA256))
  257. {
  258. NRF_LOG_WARNING("Boot validation failed. The boot validation of the app must be a signature check.");
  259. return false;
  260. }
  261. else if (SD_PRESENT && !boot_validate(&s_dfu_settings.boot_validation_softdevice, MBR_SIZE, s_dfu_settings.sd_size, do_crc))
  262. {
  263. NRF_LOG_WARNING("Boot validation failed. SoftDevice is present but invalid.");
  264. return false;
  265. }
  266. else if (!boot_validate(&s_dfu_settings.boot_validation_app, nrf_dfu_bank0_start_addr(), s_dfu_settings.bank_0.image_size, do_crc))
  267. {
  268. NRF_LOG_WARNING("Boot validation failed. App is invalid.");
  269. return false;
  270. }
  271. // The bootloader itself is not checked, since a self-check of this kind gives little to no benefit
  272. // compared to the cost incurred on each bootup.
  273. NRF_LOG_DEBUG("App is valid");
  274. return true;
  275. }
  276. /**@brief Function for clearing all DFU enter flags that
  277. * preserve state during reset.
  278. *
  279. * @details This is used to make sure that each of these flags
  280. * is checked only once after reset.
  281. */
  282. static void dfu_enter_flags_clear(void)
  283. {
  284. if (NRF_BL_DFU_ENTER_METHOD_PINRESET &&
  285. (NRF_POWER->RESETREAS & POWER_RESETREAS_RESETPIN_Msk))
  286. {
  287. // Clear RESETPIN flag.
  288. NRF_POWER->RESETREAS |= POWER_RESETREAS_RESETPIN_Msk;
  289. }
  290. if (NRF_BL_DFU_ENTER_METHOD_GPREGRET &&
  291. ((nrf_power_gpregret_get() & BOOTLOADER_DFU_GPREGRET_MASK) == BOOTLOADER_DFU_GPREGRET)
  292. && (nrf_power_gpregret_get() & BOOTLOADER_DFU_START_BIT_MASK))
  293. {
  294. // Clear DFU mark in GPREGRET register.
  295. nrf_power_gpregret_set(nrf_power_gpregret_get() & ~BOOTLOADER_DFU_START);
  296. }
  297. if (NRF_BL_DFU_ENTER_METHOD_BUTTONLESS &&
  298. (s_dfu_settings.enter_buttonless_dfu == 1))
  299. {
  300. // Clear DFU flag in flash settings.
  301. s_dfu_settings.enter_buttonless_dfu = 0;
  302. APP_ERROR_CHECK(nrf_dfu_settings_write(NULL));
  303. }
  304. }
  305. /**@brief Function for checking whether to enter DFU mode or not.
  306. */
  307. static bool dfu_enter_check(void)
  308. {
  309. if (!app_is_valid(crc_on_valid_app_required()))
  310. {
  311. NRF_LOG_DEBUG("DFU mode because app is not valid.");
  312. return true;
  313. }
  314. if (NRF_BL_DFU_ENTER_METHOD_BUTTON &&
  315. (nrf_gpio_pin_read(NRF_BL_DFU_ENTER_METHOD_BUTTON_PIN) == 0))
  316. {
  317. NRF_LOG_DEBUG("DFU mode requested via button.");
  318. return true;
  319. }
  320. if (NRF_BL_DFU_ENTER_METHOD_PINRESET &&
  321. (NRF_POWER->RESETREAS & POWER_RESETREAS_RESETPIN_Msk))
  322. {
  323. NRF_LOG_DEBUG("DFU mode requested via pin-reset.");
  324. return true;
  325. }
  326. if (NRF_BL_DFU_ENTER_METHOD_GPREGRET &&
  327. (nrf_power_gpregret_get() & BOOTLOADER_DFU_START))
  328. {
  329. NRF_LOG_DEBUG("DFU mode requested via GPREGRET.");
  330. return true;
  331. }
  332. if (NRF_BL_DFU_ENTER_METHOD_BUTTONLESS &&
  333. (s_dfu_settings.enter_buttonless_dfu == 1))
  334. {
  335. NRF_LOG_DEBUG("DFU mode requested via bootloader settings.");
  336. return true;
  337. }
  338. return false;
  339. }
  340. #if NRF_BL_DFU_ALLOW_UPDATE_FROM_APP
  341. static void postvalidate(void)
  342. {
  343. NRF_LOG_INFO("Postvalidating update after reset.");
  344. nrf_dfu_validation_init();
  345. if (nrf_dfu_validation_init_cmd_present())
  346. {
  347. uint32_t firmware_start_addr;
  348. uint32_t firmware_size;
  349. // Execute a previously received init packed. Subsequent executes will have no effect.
  350. if (nrf_dfu_validation_init_cmd_execute(&firmware_start_addr, &firmware_size) == NRF_DFU_RES_CODE_SUCCESS)
  351. {
  352. if (nrf_dfu_validation_prevalidate() == NRF_DFU_RES_CODE_SUCCESS)
  353. {
  354. if (nrf_dfu_validation_activation_prepare(firmware_start_addr, firmware_size) == NRF_DFU_RES_CODE_SUCCESS)
  355. {
  356. NRF_LOG_INFO("Postvalidation successful.");
  357. }
  358. }
  359. }
  360. }
  361. s_dfu_settings.bank_current = NRF_DFU_CURRENT_BANK_0;
  362. UNUSED_RETURN_VALUE(nrf_dfu_settings_write_and_backup(flash_write_callback));
  363. }
  364. #endif
  365. // MAC ADDRESS DISPLAY jakuja
  366. void get_bd_addr(void)
  367. {
  368. ret_code_t ret_code;
  369. ble_gap_addr_t gap_addr;
  370. ret_code = sd_ble_gap_addr_get(&gap_addr);
  371. APP_ERROR_CHECK(ret_code);
  372. //NRF_LOG_INFO("Get bd address to: %02X:%02X:%02X:%02X:%02X:%02X",
  373. NRF_LOG_INFO("Get bd address to: %02X %02X %02X",
  374. //gap_addr.addr[0],
  375. //gap_addr.addr[1],
  376. //gap_addr.addr[2],
  377. gap_addr.addr[3],
  378. gap_addr.addr[4],
  379. gap_addr.addr[5]);
  380. }
  381. ret_code_t nrf_bootloader_init(nrf_dfu_observer_t observer)
  382. {
  383. NRF_LOG_DEBUG("In nrf_bootloader_init");
  384. ret_code_t ret_val;
  385. nrf_bootloader_fw_activation_result_t activation_result;
  386. uint32_t initial_timeout;
  387. bool dfu_enter = false;
  388. m_user_observer = observer;
  389. if (NRF_BL_DEBUG_PORT_DISABLE)
  390. {
  391. nrf_bootloader_debug_port_disable();
  392. }
  393. #if NRF_BL_DFU_ENTER_METHOD_BUTTON
  394. dfu_enter_button_init();
  395. #endif
  396. ret_val = nrf_dfu_settings_init(false);
  397. if (ret_val != NRF_SUCCESS)
  398. {
  399. return NRF_ERROR_INTERNAL;
  400. }
  401. #if NRF_BL_DFU_ALLOW_UPDATE_FROM_APP
  402. // Postvalidate if DFU has signaled that update is ready.
  403. if (s_dfu_settings.bank_current == NRF_DFU_CURRENT_BANK_1)
  404. {
  405. postvalidate();
  406. }
  407. #endif
  408. // Check if an update needs to be activated and activate it.
  409. activation_result = nrf_bootloader_fw_activate();
  410. switch (activation_result)
  411. {
  412. case ACTIVATION_NONE:
  413. initial_timeout = NRF_BOOTLOADER_MS_TO_TICKS(NRF_BL_DFU_INACTIVITY_TIMEOUT_MS);
  414. dfu_enter = dfu_enter_check();
  415. break;
  416. case ACTIVATION_SUCCESS_EXPECT_ADDITIONAL_UPDATE:
  417. initial_timeout = NRF_BOOTLOADER_MS_TO_TICKS(NRF_BL_DFU_CONTINUATION_TIMEOUT_MS);
  418. dfu_enter = true;
  419. break;
  420. case ACTIVATION_SUCCESS:
  421. bootloader_reset(true);
  422. NRF_LOG_ERROR("Unreachable");
  423. return NRF_ERROR_INTERNAL; // Should not reach this.
  424. case ACTIVATION_ERROR:
  425. default:
  426. return NRF_ERROR_INTERNAL;
  427. }
  428. NRF_LOG_DEBUG("=============");
  429. if (dfu_enter)
  430. {
  431. nrf_bootloader_wdt_init();
  432. scheduler_init();
  433. dfu_enter_flags_clear();
  434. // Call user-defined init function if implemented
  435. ret_val = nrf_dfu_init_user();
  436. if (ret_val != NRF_SUCCESS)
  437. {
  438. return NRF_ERROR_INTERNAL;
  439. }
  440. nrf_bootloader_dfu_inactivity_timer_restart(initial_timeout, inactivity_timeout);
  441. ret_val = nrf_dfu_init(dfu_observer);
  442. if (ret_val != NRF_SUCCESS)
  443. {
  444. return NRF_ERROR_INTERNAL;
  445. }
  446. // get_bd_addr();
  447. NRF_LOG_DEBUG("Enter main loop");
  448. get_bd_addr();
  449. loop_forever(); // This function will never return.
  450. NRF_LOG_ERROR("Unreachable");
  451. }
  452. else
  453. {
  454. // Erase additional data like peer data or advertisement name
  455. ret_val = nrf_dfu_settings_additional_erase();
  456. if (ret_val != NRF_SUCCESS)
  457. {
  458. return NRF_ERROR_INTERNAL;
  459. }
  460. m_flash_write_done = false;
  461. nrf_dfu_settings_backup(flash_write_callback);
  462. ASSERT(m_flash_write_done);
  463. nrf_bootloader_app_start();
  464. NRF_LOG_ERROR("Unreachable");
  465. }
  466. // Should not be reached.
  467. return NRF_ERROR_INTERNAL;
  468. }