main.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419
  1. /*
  2. * This file is part of the MicroPython project, http://micropython.org/
  3. *
  4. * The MIT License (MIT)
  5. *
  6. * Copyright (c) 2015 Daniel Campora
  7. *
  8. * Permission is hereby granted, free of charge, to any person obtaining a copy
  9. * of this software and associated documentation files (the "Software"), to deal
  10. * in the Software without restriction, including without limitation the rights
  11. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  12. * copies of the Software, and to permit persons to whom the Software is
  13. * furnished to do so, subject to the following conditions:
  14. *
  15. * The above copyright notice and this permission notice shall be included in
  16. * all copies or substantial portions of the Software.
  17. *
  18. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  19. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  20. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  21. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  22. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  23. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  24. * THE SOFTWARE.
  25. */
  26. #include <stdint.h>
  27. #include <stdbool.h>
  28. #include <stdio.h>
  29. #include "py/mpconfig.h"
  30. #include "hw_ints.h"
  31. #include "hw_types.h"
  32. #include "hw_gpio.h"
  33. #include "hw_memmap.h"
  34. #include "hw_gprcm.h"
  35. #include "hw_common_reg.h"
  36. #include "pin.h"
  37. #include "gpio.h"
  38. #include "rom_map.h"
  39. #include "prcm.h"
  40. #include "simplelink.h"
  41. #include "interrupt.h"
  42. #include "gpio.h"
  43. #include "flc.h"
  44. #include "bootmgr.h"
  45. #include "shamd5.h"
  46. #include "cryptohash.h"
  47. #include "utils.h"
  48. #include "cc3200_hal.h"
  49. #include "debug.h"
  50. #include "mperror.h"
  51. #include "antenna.h"
  52. //*****************************************************************************
  53. // Local Constants
  54. //*****************************************************************************
  55. #define SL_STOP_TIMEOUT 35
  56. #define BOOTMGR_HASH_ALGO SHAMD5_ALGO_MD5
  57. #define BOOTMGR_HASH_SIZE 32
  58. #define BOOTMGR_BUFF_SIZE 512
  59. #define BOOTMGR_WAIT_SAFE_MODE_0_MS 500
  60. #define BOOTMGR_WAIT_SAFE_MODE_1_MS 3000
  61. #define BOOTMGR_WAIT_SAFE_MODE_1_BLINK_MS 500
  62. #define BOOTMGR_WAIT_SAFE_MODE_2_MS 3000
  63. #define BOOTMGR_WAIT_SAFE_MODE_2_BLINK_MS 250
  64. #define BOOTMGR_WAIT_SAFE_MODE_3_MS 1500
  65. #define BOOTMGR_WAIT_SAFE_MODE_3_BLINK_MS 100
  66. //*****************************************************************************
  67. // Exported functions declarations
  68. //*****************************************************************************
  69. extern void bootmgr_run_app (_u32 base);
  70. //*****************************************************************************
  71. // Local functions declarations
  72. //*****************************************************************************
  73. static void bootmgr_board_init (void);
  74. static bool bootmgr_verify (_u8 *image);
  75. static void bootmgr_load_and_execute (_u8 *image);
  76. static bool wait_while_blinking (uint32_t wait_time, uint32_t period, bool force_wait);
  77. static bool safe_boot_request_start (uint32_t wait_time);
  78. static void wait_for_safe_boot (sBootInfo_t *psBootInfo);
  79. static void bootmgr_image_loader (sBootInfo_t *psBootInfo);
  80. //*****************************************************************************
  81. // Private data
  82. //*****************************************************************************
  83. static _u8 bootmgr_file_buf[BOOTMGR_BUFF_SIZE];
  84. static _u8 bootmgr_hash_buf[BOOTMGR_HASH_SIZE + 1];
  85. //*****************************************************************************
  86. // Vector Table
  87. //*****************************************************************************
  88. extern void (* const g_pfnVectors[])(void);
  89. //*****************************************************************************
  90. // WLAN Event handler callback hookup function
  91. //*****************************************************************************
  92. void SimpleLinkWlanEventHandler(SlWlanEvent_t *pWlanEvent)
  93. {
  94. }
  95. //*****************************************************************************
  96. // HTTP Server callback hookup function
  97. //*****************************************************************************
  98. void SimpleLinkHttpServerCallback(SlHttpServerEvent_t *pHttpEvent,
  99. SlHttpServerResponse_t *pHttpResponse)
  100. {
  101. }
  102. //*****************************************************************************
  103. // Net APP Event callback hookup function
  104. //*****************************************************************************
  105. void SimpleLinkNetAppEventHandler(SlNetAppEvent_t *pNetAppEvent)
  106. {
  107. }
  108. //*****************************************************************************
  109. // General Event callback hookup function
  110. //*****************************************************************************
  111. void SimpleLinkGeneralEventHandler(SlDeviceEvent_t *pDevEvent)
  112. {
  113. }
  114. //*****************************************************************************
  115. // Socket Event callback hookup function
  116. //*****************************************************************************
  117. void SimpleLinkSockEventHandler(SlSockEvent_t *pSock)
  118. {
  119. }
  120. //*****************************************************************************
  121. //! Board Initialization & Configuration
  122. //*****************************************************************************
  123. static void bootmgr_board_init(void) {
  124. // set the vector table base
  125. MAP_IntVTableBaseSet((unsigned long)&g_pfnVectors[0]);
  126. // enable processor interrupts
  127. MAP_IntMasterEnable();
  128. MAP_IntEnable(FAULT_SYSTICK);
  129. // mandatory MCU initialization
  130. PRCMCC3200MCUInit();
  131. // clear all the special bits, since we can't trust their content after reset
  132. // except for the WDT reset one!!
  133. PRCMClearSpecialBit(PRCM_SAFE_BOOT_BIT);
  134. PRCMClearSpecialBit(PRCM_FIRST_BOOT_BIT);
  135. // check the reset after clearing the special bits
  136. mperror_bootloader_check_reset_cause();
  137. #if MICROPY_HW_ANTENNA_DIVERSITY
  138. // configure the antenna selection pins
  139. antenna_init0();
  140. #endif
  141. // enable the data hashing engine
  142. CRYPTOHASH_Init();
  143. // init the system led and the system switch
  144. mperror_init0();
  145. }
  146. //*****************************************************************************
  147. //! Verifies the integrity of the new application binary
  148. //*****************************************************************************
  149. static bool bootmgr_verify (_u8 *image) {
  150. SlFsFileInfo_t FsFileInfo;
  151. _u32 reqlen, offset = 0;
  152. _i32 fHandle;
  153. // open the file for reading
  154. if (0 == sl_FsOpen(image, FS_MODE_OPEN_READ, NULL, &fHandle)) {
  155. // get the file size
  156. sl_FsGetInfo(image, 0, &FsFileInfo);
  157. if (FsFileInfo.FileLen > BOOTMGR_HASH_SIZE) {
  158. FsFileInfo.FileLen -= BOOTMGR_HASH_SIZE;
  159. CRYPTOHASH_SHAMD5Start(BOOTMGR_HASH_ALGO, FsFileInfo.FileLen);
  160. do {
  161. if ((FsFileInfo.FileLen - offset) > BOOTMGR_BUFF_SIZE) {
  162. reqlen = BOOTMGR_BUFF_SIZE;
  163. }
  164. else {
  165. reqlen = FsFileInfo.FileLen - offset;
  166. }
  167. offset += sl_FsRead(fHandle, offset, bootmgr_file_buf, reqlen);
  168. CRYPTOHASH_SHAMD5Update(bootmgr_file_buf, reqlen);
  169. } while (offset < FsFileInfo.FileLen);
  170. CRYPTOHASH_SHAMD5Read (bootmgr_file_buf);
  171. // convert the resulting hash to hex
  172. for (_u32 i = 0; i < (BOOTMGR_HASH_SIZE / 2); i++) {
  173. snprintf ((char *)&bootmgr_hash_buf[(i * 2)], 3, "%02x", bootmgr_file_buf[i]);
  174. }
  175. // read the hash from the file and close it
  176. sl_FsRead(fHandle, offset, bootmgr_file_buf, BOOTMGR_HASH_SIZE);
  177. sl_FsClose (fHandle, NULL, NULL, 0);
  178. bootmgr_file_buf[BOOTMGR_HASH_SIZE] = '\0';
  179. // compare both hashes
  180. if (!strcmp((const char *)bootmgr_hash_buf, (const char *)bootmgr_file_buf)) {
  181. // it's a match
  182. return true;
  183. }
  184. }
  185. // close the file
  186. sl_FsClose(fHandle, NULL, NULL, 0);
  187. }
  188. return false;
  189. }
  190. //*****************************************************************************
  191. //! Loads the application from sFlash and executes
  192. //*****************************************************************************
  193. static void bootmgr_load_and_execute (_u8 *image) {
  194. SlFsFileInfo_t pFsFileInfo;
  195. _i32 fhandle;
  196. // open the application binary
  197. if (!sl_FsOpen(image, FS_MODE_OPEN_READ, NULL, &fhandle)) {
  198. // get the file size
  199. if (!sl_FsGetInfo(image, 0, &pFsFileInfo)) {
  200. // read the application into SRAM
  201. if (pFsFileInfo.FileLen == sl_FsRead(fhandle, 0, (unsigned char *)APP_IMG_SRAM_OFFSET, pFsFileInfo.FileLen)) {
  202. // close the file
  203. sl_FsClose(fhandle, 0, 0, 0);
  204. // stop the network services
  205. sl_Stop(SL_STOP_TIMEOUT);
  206. // execute the application
  207. bootmgr_run_app(APP_IMG_SRAM_OFFSET);
  208. }
  209. }
  210. }
  211. }
  212. //*****************************************************************************
  213. //! Wait while the safe mode pin is being held high and blink the system led
  214. //! with the specified period
  215. //*****************************************************************************
  216. static bool wait_while_blinking (uint32_t wait_time, uint32_t period, bool force_wait) {
  217. _u32 count;
  218. for (count = 0; (force_wait || MAP_GPIOPinRead(MICROPY_SAFE_BOOT_PORT, MICROPY_SAFE_BOOT_PORT_PIN)) &&
  219. ((period * count) < wait_time); count++) {
  220. // toogle the led
  221. MAP_GPIOPinWrite(MICROPY_SYS_LED_PORT, MICROPY_SYS_LED_PORT_PIN, ~MAP_GPIOPinRead(MICROPY_SYS_LED_PORT, MICROPY_SYS_LED_PORT_PIN));
  222. UtilsDelay(UTILS_DELAY_US_TO_COUNT(period * 1000));
  223. }
  224. return MAP_GPIOPinRead(MICROPY_SAFE_BOOT_PORT, MICROPY_SAFE_BOOT_PORT_PIN) ? true : false;
  225. }
  226. static bool safe_boot_request_start (uint32_t wait_time) {
  227. if (MAP_GPIOPinRead(MICROPY_SAFE_BOOT_PORT, MICROPY_SAFE_BOOT_PORT_PIN)) {
  228. UtilsDelay(UTILS_DELAY_US_TO_COUNT(wait_time * 1000));
  229. }
  230. return MAP_GPIOPinRead(MICROPY_SAFE_BOOT_PORT, MICROPY_SAFE_BOOT_PORT_PIN) ? true : false;
  231. }
  232. //*****************************************************************************
  233. //! Check for the safe mode pin
  234. //*****************************************************************************
  235. static void wait_for_safe_boot (sBootInfo_t *psBootInfo) {
  236. if (safe_boot_request_start(BOOTMGR_WAIT_SAFE_MODE_0_MS)) {
  237. if (wait_while_blinking(BOOTMGR_WAIT_SAFE_MODE_1_MS, BOOTMGR_WAIT_SAFE_MODE_1_BLINK_MS, false)) {
  238. // go back one step in time
  239. psBootInfo->ActiveImg = psBootInfo->PrevImg;
  240. if (wait_while_blinking(BOOTMGR_WAIT_SAFE_MODE_2_MS, BOOTMGR_WAIT_SAFE_MODE_2_BLINK_MS, false)) {
  241. // go back directly to the factory image
  242. psBootInfo->ActiveImg = IMG_ACT_FACTORY;
  243. wait_while_blinking(BOOTMGR_WAIT_SAFE_MODE_3_MS, BOOTMGR_WAIT_SAFE_MODE_3_BLINK_MS, true);
  244. }
  245. }
  246. // turn off the system led
  247. MAP_GPIOPinWrite(MICROPY_SYS_LED_PORT, MICROPY_SYS_LED_PORT_PIN, 0);
  248. // request a safe boot to the application
  249. PRCMSetSpecialBit(PRCM_SAFE_BOOT_BIT);
  250. }
  251. // deinit the safe boot pin
  252. mperror_deinit_sfe_pin();
  253. }
  254. //*****************************************************************************
  255. //! Load the proper image based on the information from the boot info
  256. //! and launch it.
  257. //*****************************************************************************
  258. static void bootmgr_image_loader(sBootInfo_t *psBootInfo) {
  259. _i32 fhandle;
  260. _u8 *image;
  261. // search for the active image
  262. switch (psBootInfo->ActiveImg) {
  263. case IMG_ACT_UPDATE1:
  264. image = (unsigned char *)IMG_UPDATE1;
  265. break;
  266. case IMG_ACT_UPDATE2:
  267. image = (unsigned char *)IMG_UPDATE2;
  268. break;
  269. default:
  270. image = (unsigned char *)IMG_FACTORY;
  271. break;
  272. }
  273. // do we have a new image that needs to be verified?
  274. if ((psBootInfo->ActiveImg != IMG_ACT_FACTORY) && (psBootInfo->Status == IMG_STATUS_CHECK)) {
  275. if (!bootmgr_verify(image)) {
  276. // verification failed, delete the broken file
  277. sl_FsDel(image, 0);
  278. // switch to the previous image
  279. psBootInfo->ActiveImg = psBootInfo->PrevImg;
  280. psBootInfo->PrevImg = IMG_ACT_FACTORY;
  281. }
  282. // in any case, change the status to "READY"
  283. psBootInfo->Status = IMG_STATUS_READY;
  284. // write the new boot info
  285. if (!sl_FsOpen((unsigned char *)IMG_BOOT_INFO, FS_MODE_OPEN_WRITE, NULL, &fhandle)) {
  286. sl_FsWrite(fhandle, 0, (unsigned char *)psBootInfo, sizeof(sBootInfo_t));
  287. // close the file
  288. sl_FsClose(fhandle, 0, 0, 0);
  289. }
  290. }
  291. // this one might modify the boot info hence it MUST be called after
  292. // bootmgr_verify! (so that the changes are not saved to flash)
  293. wait_for_safe_boot(psBootInfo);
  294. // select the active image again, since it might have changed
  295. switch (psBootInfo->ActiveImg) {
  296. case IMG_ACT_UPDATE1:
  297. image = (unsigned char *)IMG_UPDATE1;
  298. break;
  299. case IMG_ACT_UPDATE2:
  300. image = (unsigned char *)IMG_UPDATE2;
  301. break;
  302. default:
  303. image = (unsigned char *)IMG_FACTORY;
  304. break;
  305. }
  306. bootmgr_load_and_execute(image);
  307. }
  308. //*****************************************************************************
  309. //! Main function
  310. //*****************************************************************************
  311. int main (void) {
  312. sBootInfo_t sBootInfo = { .ActiveImg = IMG_ACT_FACTORY, .Status = IMG_STATUS_READY, .PrevImg = IMG_ACT_FACTORY };
  313. bool bootapp = false;
  314. _i32 fhandle;
  315. // board setup
  316. bootmgr_board_init();
  317. // start simplelink since we need it to access the sflash
  318. sl_Start(0, 0, 0);
  319. // if a boot info file is found, load it, else, create a new one with the default boot info
  320. if (!sl_FsOpen((unsigned char *)IMG_BOOT_INFO, FS_MODE_OPEN_READ, NULL, &fhandle)) {
  321. if (sizeof(sBootInfo_t) == sl_FsRead(fhandle, 0, (unsigned char *)&sBootInfo, sizeof(sBootInfo_t))) {
  322. bootapp = true;
  323. }
  324. sl_FsClose(fhandle, 0, 0, 0);
  325. }
  326. // boot info file not present, it means that this is the first boot after being programmed
  327. if (!bootapp) {
  328. // create a new boot info file
  329. _u32 BootInfoCreateFlag = _FS_FILE_OPEN_FLAG_COMMIT | _FS_FILE_PUBLIC_WRITE | _FS_FILE_PUBLIC_READ;
  330. if (!sl_FsOpen ((unsigned char *)IMG_BOOT_INFO, FS_MODE_OPEN_CREATE((2 * sizeof(sBootInfo_t)),
  331. BootInfoCreateFlag), NULL, &fhandle)) {
  332. // write the default boot info.
  333. if (sizeof(sBootInfo_t) == sl_FsWrite(fhandle, 0, (unsigned char *)&sBootInfo, sizeof(sBootInfo_t))) {
  334. bootapp = true;
  335. }
  336. sl_FsClose(fhandle, 0, 0, 0);
  337. }
  338. // signal the first boot to the application
  339. PRCMSetSpecialBit(PRCM_FIRST_BOOT_BIT);
  340. }
  341. if (bootapp) {
  342. // load and execute the image based on the boot info
  343. bootmgr_image_loader(&sBootInfo);
  344. }
  345. // stop simplelink
  346. sl_Stop(SL_STOP_TIMEOUT);
  347. // if we've reached this point, then it means that a fatal error has occurred and the
  348. // application could not be loaded, so, loop forever and signal the crash to the user
  349. while (true) {
  350. // keep the bld on
  351. MAP_GPIOPinWrite(MICROPY_SYS_LED_PORT, MICROPY_SYS_LED_PORT_PIN, MICROPY_SYS_LED_PORT_PIN);
  352. __asm volatile(" dsb \n"
  353. " isb \n"
  354. " wfi \n");
  355. }
  356. }
  357. //*****************************************************************************
  358. //! The following stub function is needed to link mp_vprintf
  359. //*****************************************************************************
  360. #include "py/qstr.h"
  361. const byte *qstr_data(qstr q, size_t *len) {
  362. *len = 0;
  363. return NULL;
  364. }