| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419 |
- /*
- * This file is part of the MicroPython project, http://micropython.org/
- *
- * The MIT License (MIT)
- *
- * Copyright (c) 2015 Daniel Campora
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
- #include <stdint.h>
- #include <stdbool.h>
- #include <stdio.h>
- #include "py/mpconfig.h"
- #include "hw_ints.h"
- #include "hw_types.h"
- #include "hw_gpio.h"
- #include "hw_memmap.h"
- #include "hw_gprcm.h"
- #include "hw_common_reg.h"
- #include "pin.h"
- #include "gpio.h"
- #include "rom_map.h"
- #include "prcm.h"
- #include "simplelink.h"
- #include "interrupt.h"
- #include "gpio.h"
- #include "flc.h"
- #include "bootmgr.h"
- #include "shamd5.h"
- #include "cryptohash.h"
- #include "utils.h"
- #include "cc3200_hal.h"
- #include "debug.h"
- #include "mperror.h"
- #include "antenna.h"
- //*****************************************************************************
- // Local Constants
- //*****************************************************************************
- #define SL_STOP_TIMEOUT 35
- #define BOOTMGR_HASH_ALGO SHAMD5_ALGO_MD5
- #define BOOTMGR_HASH_SIZE 32
- #define BOOTMGR_BUFF_SIZE 512
- #define BOOTMGR_WAIT_SAFE_MODE_0_MS 500
- #define BOOTMGR_WAIT_SAFE_MODE_1_MS 3000
- #define BOOTMGR_WAIT_SAFE_MODE_1_BLINK_MS 500
- #define BOOTMGR_WAIT_SAFE_MODE_2_MS 3000
- #define BOOTMGR_WAIT_SAFE_MODE_2_BLINK_MS 250
- #define BOOTMGR_WAIT_SAFE_MODE_3_MS 1500
- #define BOOTMGR_WAIT_SAFE_MODE_3_BLINK_MS 100
- //*****************************************************************************
- // Exported functions declarations
- //*****************************************************************************
- extern void bootmgr_run_app (_u32 base);
- //*****************************************************************************
- // Local functions declarations
- //*****************************************************************************
- static void bootmgr_board_init (void);
- static bool bootmgr_verify (_u8 *image);
- static void bootmgr_load_and_execute (_u8 *image);
- static bool wait_while_blinking (uint32_t wait_time, uint32_t period, bool force_wait);
- static bool safe_boot_request_start (uint32_t wait_time);
- static void wait_for_safe_boot (sBootInfo_t *psBootInfo);
- static void bootmgr_image_loader (sBootInfo_t *psBootInfo);
- //*****************************************************************************
- // Private data
- //*****************************************************************************
- static _u8 bootmgr_file_buf[BOOTMGR_BUFF_SIZE];
- static _u8 bootmgr_hash_buf[BOOTMGR_HASH_SIZE + 1];
- //*****************************************************************************
- // Vector Table
- //*****************************************************************************
- extern void (* const g_pfnVectors[])(void);
- //*****************************************************************************
- // WLAN Event handler callback hookup function
- //*****************************************************************************
- void SimpleLinkWlanEventHandler(SlWlanEvent_t *pWlanEvent)
- {
- }
- //*****************************************************************************
- // HTTP Server callback hookup function
- //*****************************************************************************
- void SimpleLinkHttpServerCallback(SlHttpServerEvent_t *pHttpEvent,
- SlHttpServerResponse_t *pHttpResponse)
- {
- }
- //*****************************************************************************
- // Net APP Event callback hookup function
- //*****************************************************************************
- void SimpleLinkNetAppEventHandler(SlNetAppEvent_t *pNetAppEvent)
- {
- }
- //*****************************************************************************
- // General Event callback hookup function
- //*****************************************************************************
- void SimpleLinkGeneralEventHandler(SlDeviceEvent_t *pDevEvent)
- {
- }
- //*****************************************************************************
- // Socket Event callback hookup function
- //*****************************************************************************
- void SimpleLinkSockEventHandler(SlSockEvent_t *pSock)
- {
- }
- //*****************************************************************************
- //! Board Initialization & Configuration
- //*****************************************************************************
- static void bootmgr_board_init(void) {
- // set the vector table base
- MAP_IntVTableBaseSet((unsigned long)&g_pfnVectors[0]);
- // enable processor interrupts
- MAP_IntMasterEnable();
- MAP_IntEnable(FAULT_SYSTICK);
- // mandatory MCU initialization
- PRCMCC3200MCUInit();
- // clear all the special bits, since we can't trust their content after reset
- // except for the WDT reset one!!
- PRCMClearSpecialBit(PRCM_SAFE_BOOT_BIT);
- PRCMClearSpecialBit(PRCM_FIRST_BOOT_BIT);
- // check the reset after clearing the special bits
- mperror_bootloader_check_reset_cause();
- #if MICROPY_HW_ANTENNA_DIVERSITY
- // configure the antenna selection pins
- antenna_init0();
- #endif
- // enable the data hashing engine
- CRYPTOHASH_Init();
- // init the system led and the system switch
- mperror_init0();
- }
- //*****************************************************************************
- //! Verifies the integrity of the new application binary
- //*****************************************************************************
- static bool bootmgr_verify (_u8 *image) {
- SlFsFileInfo_t FsFileInfo;
- _u32 reqlen, offset = 0;
- _i32 fHandle;
- // open the file for reading
- if (0 == sl_FsOpen(image, FS_MODE_OPEN_READ, NULL, &fHandle)) {
- // get the file size
- sl_FsGetInfo(image, 0, &FsFileInfo);
- if (FsFileInfo.FileLen > BOOTMGR_HASH_SIZE) {
- FsFileInfo.FileLen -= BOOTMGR_HASH_SIZE;
- CRYPTOHASH_SHAMD5Start(BOOTMGR_HASH_ALGO, FsFileInfo.FileLen);
- do {
- if ((FsFileInfo.FileLen - offset) > BOOTMGR_BUFF_SIZE) {
- reqlen = BOOTMGR_BUFF_SIZE;
- }
- else {
- reqlen = FsFileInfo.FileLen - offset;
- }
- offset += sl_FsRead(fHandle, offset, bootmgr_file_buf, reqlen);
- CRYPTOHASH_SHAMD5Update(bootmgr_file_buf, reqlen);
- } while (offset < FsFileInfo.FileLen);
- CRYPTOHASH_SHAMD5Read (bootmgr_file_buf);
- // convert the resulting hash to hex
- for (_u32 i = 0; i < (BOOTMGR_HASH_SIZE / 2); i++) {
- snprintf ((char *)&bootmgr_hash_buf[(i * 2)], 3, "%02x", bootmgr_file_buf[i]);
- }
- // read the hash from the file and close it
- sl_FsRead(fHandle, offset, bootmgr_file_buf, BOOTMGR_HASH_SIZE);
- sl_FsClose (fHandle, NULL, NULL, 0);
- bootmgr_file_buf[BOOTMGR_HASH_SIZE] = '\0';
- // compare both hashes
- if (!strcmp((const char *)bootmgr_hash_buf, (const char *)bootmgr_file_buf)) {
- // it's a match
- return true;
- }
- }
- // close the file
- sl_FsClose(fHandle, NULL, NULL, 0);
- }
- return false;
- }
- //*****************************************************************************
- //! Loads the application from sFlash and executes
- //*****************************************************************************
- static void bootmgr_load_and_execute (_u8 *image) {
- SlFsFileInfo_t pFsFileInfo;
- _i32 fhandle;
- // open the application binary
- if (!sl_FsOpen(image, FS_MODE_OPEN_READ, NULL, &fhandle)) {
- // get the file size
- if (!sl_FsGetInfo(image, 0, &pFsFileInfo)) {
- // read the application into SRAM
- if (pFsFileInfo.FileLen == sl_FsRead(fhandle, 0, (unsigned char *)APP_IMG_SRAM_OFFSET, pFsFileInfo.FileLen)) {
- // close the file
- sl_FsClose(fhandle, 0, 0, 0);
- // stop the network services
- sl_Stop(SL_STOP_TIMEOUT);
- // execute the application
- bootmgr_run_app(APP_IMG_SRAM_OFFSET);
- }
- }
- }
- }
- //*****************************************************************************
- //! Wait while the safe mode pin is being held high and blink the system led
- //! with the specified period
- //*****************************************************************************
- static bool wait_while_blinking (uint32_t wait_time, uint32_t period, bool force_wait) {
- _u32 count;
- for (count = 0; (force_wait || MAP_GPIOPinRead(MICROPY_SAFE_BOOT_PORT, MICROPY_SAFE_BOOT_PORT_PIN)) &&
- ((period * count) < wait_time); count++) {
- // toogle the led
- MAP_GPIOPinWrite(MICROPY_SYS_LED_PORT, MICROPY_SYS_LED_PORT_PIN, ~MAP_GPIOPinRead(MICROPY_SYS_LED_PORT, MICROPY_SYS_LED_PORT_PIN));
- UtilsDelay(UTILS_DELAY_US_TO_COUNT(period * 1000));
- }
- return MAP_GPIOPinRead(MICROPY_SAFE_BOOT_PORT, MICROPY_SAFE_BOOT_PORT_PIN) ? true : false;
- }
- static bool safe_boot_request_start (uint32_t wait_time) {
- if (MAP_GPIOPinRead(MICROPY_SAFE_BOOT_PORT, MICROPY_SAFE_BOOT_PORT_PIN)) {
- UtilsDelay(UTILS_DELAY_US_TO_COUNT(wait_time * 1000));
- }
- return MAP_GPIOPinRead(MICROPY_SAFE_BOOT_PORT, MICROPY_SAFE_BOOT_PORT_PIN) ? true : false;
- }
- //*****************************************************************************
- //! Check for the safe mode pin
- //*****************************************************************************
- static void wait_for_safe_boot (sBootInfo_t *psBootInfo) {
- if (safe_boot_request_start(BOOTMGR_WAIT_SAFE_MODE_0_MS)) {
- if (wait_while_blinking(BOOTMGR_WAIT_SAFE_MODE_1_MS, BOOTMGR_WAIT_SAFE_MODE_1_BLINK_MS, false)) {
- // go back one step in time
- psBootInfo->ActiveImg = psBootInfo->PrevImg;
- if (wait_while_blinking(BOOTMGR_WAIT_SAFE_MODE_2_MS, BOOTMGR_WAIT_SAFE_MODE_2_BLINK_MS, false)) {
- // go back directly to the factory image
- psBootInfo->ActiveImg = IMG_ACT_FACTORY;
- wait_while_blinking(BOOTMGR_WAIT_SAFE_MODE_3_MS, BOOTMGR_WAIT_SAFE_MODE_3_BLINK_MS, true);
- }
- }
- // turn off the system led
- MAP_GPIOPinWrite(MICROPY_SYS_LED_PORT, MICROPY_SYS_LED_PORT_PIN, 0);
- // request a safe boot to the application
- PRCMSetSpecialBit(PRCM_SAFE_BOOT_BIT);
- }
- // deinit the safe boot pin
- mperror_deinit_sfe_pin();
- }
- //*****************************************************************************
- //! Load the proper image based on the information from the boot info
- //! and launch it.
- //*****************************************************************************
- static void bootmgr_image_loader(sBootInfo_t *psBootInfo) {
- _i32 fhandle;
- _u8 *image;
- // search for the active image
- switch (psBootInfo->ActiveImg) {
- case IMG_ACT_UPDATE1:
- image = (unsigned char *)IMG_UPDATE1;
- break;
- case IMG_ACT_UPDATE2:
- image = (unsigned char *)IMG_UPDATE2;
- break;
- default:
- image = (unsigned char *)IMG_FACTORY;
- break;
- }
- // do we have a new image that needs to be verified?
- if ((psBootInfo->ActiveImg != IMG_ACT_FACTORY) && (psBootInfo->Status == IMG_STATUS_CHECK)) {
- if (!bootmgr_verify(image)) {
- // verification failed, delete the broken file
- sl_FsDel(image, 0);
- // switch to the previous image
- psBootInfo->ActiveImg = psBootInfo->PrevImg;
- psBootInfo->PrevImg = IMG_ACT_FACTORY;
- }
- // in any case, change the status to "READY"
- psBootInfo->Status = IMG_STATUS_READY;
- // write the new boot info
- if (!sl_FsOpen((unsigned char *)IMG_BOOT_INFO, FS_MODE_OPEN_WRITE, NULL, &fhandle)) {
- sl_FsWrite(fhandle, 0, (unsigned char *)psBootInfo, sizeof(sBootInfo_t));
- // close the file
- sl_FsClose(fhandle, 0, 0, 0);
- }
- }
- // this one might modify the boot info hence it MUST be called after
- // bootmgr_verify! (so that the changes are not saved to flash)
- wait_for_safe_boot(psBootInfo);
- // select the active image again, since it might have changed
- switch (psBootInfo->ActiveImg) {
- case IMG_ACT_UPDATE1:
- image = (unsigned char *)IMG_UPDATE1;
- break;
- case IMG_ACT_UPDATE2:
- image = (unsigned char *)IMG_UPDATE2;
- break;
- default:
- image = (unsigned char *)IMG_FACTORY;
- break;
- }
- bootmgr_load_and_execute(image);
- }
- //*****************************************************************************
- //! Main function
- //*****************************************************************************
- int main (void) {
- sBootInfo_t sBootInfo = { .ActiveImg = IMG_ACT_FACTORY, .Status = IMG_STATUS_READY, .PrevImg = IMG_ACT_FACTORY };
- bool bootapp = false;
- _i32 fhandle;
- // board setup
- bootmgr_board_init();
- // start simplelink since we need it to access the sflash
- sl_Start(0, 0, 0);
- // if a boot info file is found, load it, else, create a new one with the default boot info
- if (!sl_FsOpen((unsigned char *)IMG_BOOT_INFO, FS_MODE_OPEN_READ, NULL, &fhandle)) {
- if (sizeof(sBootInfo_t) == sl_FsRead(fhandle, 0, (unsigned char *)&sBootInfo, sizeof(sBootInfo_t))) {
- bootapp = true;
- }
- sl_FsClose(fhandle, 0, 0, 0);
- }
- // boot info file not present, it means that this is the first boot after being programmed
- if (!bootapp) {
- // create a new boot info file
- _u32 BootInfoCreateFlag = _FS_FILE_OPEN_FLAG_COMMIT | _FS_FILE_PUBLIC_WRITE | _FS_FILE_PUBLIC_READ;
- if (!sl_FsOpen ((unsigned char *)IMG_BOOT_INFO, FS_MODE_OPEN_CREATE((2 * sizeof(sBootInfo_t)),
- BootInfoCreateFlag), NULL, &fhandle)) {
- // write the default boot info.
- if (sizeof(sBootInfo_t) == sl_FsWrite(fhandle, 0, (unsigned char *)&sBootInfo, sizeof(sBootInfo_t))) {
- bootapp = true;
- }
- sl_FsClose(fhandle, 0, 0, 0);
- }
- // signal the first boot to the application
- PRCMSetSpecialBit(PRCM_FIRST_BOOT_BIT);
- }
- if (bootapp) {
- // load and execute the image based on the boot info
- bootmgr_image_loader(&sBootInfo);
- }
- // stop simplelink
- sl_Stop(SL_STOP_TIMEOUT);
- // if we've reached this point, then it means that a fatal error has occurred and the
- // application could not be loaded, so, loop forever and signal the crash to the user
- while (true) {
- // keep the bld on
- MAP_GPIOPinWrite(MICROPY_SYS_LED_PORT, MICROPY_SYS_LED_PORT_PIN, MICROPY_SYS_LED_PORT_PIN);
- __asm volatile(" dsb \n"
- " isb \n"
- " wfi \n");
- }
- }
- //*****************************************************************************
- //! The following stub function is needed to link mp_vprintf
- //*****************************************************************************
- #include "py/qstr.h"
- const byte *qstr_data(qstr q, size_t *len) {
- *len = 0;
- return NULL;
- }
|