359 lines
14 KiB
C
359 lines
14 KiB
C
/*
|
|
* This file is part of the Micro Python 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 <std.h>
|
|
|
|
#include "py/mpconfig.h"
|
|
#include MICROPY_HAL_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.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 "hash.h"
|
|
#include "utils.h"
|
|
#include "cc3200_hal.h"
|
|
#include "debug.h"
|
|
#include "mperror.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_MS 1600
|
|
#define BOOTMGR_WAIT_SAFE_MODE_TOOGLE_MS 200
|
|
|
|
#define BOOTMGR_SAFE_MODE_ENTER_MS 800
|
|
#define BOOTMGR_SAFE_MODE_ENTER_TOOGLE_MS 80
|
|
|
|
//*****************************************************************************
|
|
// Exported functions declarations
|
|
//*****************************************************************************
|
|
extern void bootmgr_run_app (_u32 base);
|
|
|
|
//*****************************************************************************
|
|
// Local functions declarations
|
|
//*****************************************************************************
|
|
static void bootmgr_board_init (void);
|
|
static bool bootmgr_verify (void);
|
|
static void bootmgr_load_and_execute (_u8 *image);
|
|
static bool safe_mode_boot (void);
|
|
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 vector table base
|
|
MAP_IntVTableBaseSet((unsigned long)&g_pfnVectors[0]);
|
|
|
|
// Enable Processor Interrupts
|
|
MAP_IntMasterEnable();
|
|
MAP_IntEnable(FAULT_SYSTICK);
|
|
|
|
// Mandatory MCU Initialization
|
|
PRCMCC3200MCUInit();
|
|
|
|
mperror_bootloader_check_reset_cause();
|
|
|
|
// Enable the Data Hashing Engine
|
|
HASH_Init();
|
|
|
|
// Init the system led and the system switch
|
|
mperror_init0();
|
|
|
|
// clear the safe boot flag, since we can't trust its content after reset
|
|
PRCMClearSafeBootRequest();
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//! Verifies the integrity of the new application binary
|
|
//*****************************************************************************
|
|
static bool bootmgr_verify (void) {
|
|
SlFsFileInfo_t FsFileInfo;
|
|
_u32 reqlen, offset = 0;
|
|
_i32 fHandle;
|
|
|
|
// open the file for reading
|
|
if (0 == sl_FsOpen((_u8 *)IMG_UPDATE, FS_MODE_OPEN_READ, NULL, &fHandle)) {
|
|
// get the file size
|
|
sl_FsGetInfo((_u8 *)IMG_UPDATE, 0, &FsFileInfo);
|
|
|
|
if (FsFileInfo.FileLen > BOOTMGR_HASH_SIZE) {
|
|
FsFileInfo.FileLen -= BOOTMGR_HASH_SIZE;
|
|
HASH_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);
|
|
HASH_SHAMD5Update(bootmgr_file_buf, reqlen);
|
|
} while (offset < FsFileInfo.FileLen);
|
|
|
|
HASH_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
|
|
ASSERT (BOOTMGR_HASH_SIZE == 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);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//! Check for the safe mode pin
|
|
//*****************************************************************************
|
|
static bool safe_mode_boot (void) {
|
|
_u32 count = 0;
|
|
while (MAP_GPIOPinRead(MICROPY_SAFE_BOOT_PORT, MICROPY_SAFE_BOOT_PORT_PIN) &&
|
|
((BOOTMGR_WAIT_SAFE_MODE_TOOGLE_MS * count++) < BOOTMGR_WAIT_SAFE_MODE_MS)) {
|
|
// 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(BOOTMGR_WAIT_SAFE_MODE_TOOGLE_MS * 1000));
|
|
}
|
|
mperror_deinit_sfe_pin();
|
|
return MAP_GPIOPinRead(MICROPY_SAFE_BOOT_PORT, MICROPY_SAFE_BOOT_PORT_PIN) ? true : false;
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//! Load the proper image based on information from boot info and executes it.
|
|
//*****************************************************************************
|
|
static void bootmgr_image_loader(sBootInfo_t *psBootInfo) {
|
|
_i32 fhandle;
|
|
if (safe_mode_boot()) {
|
|
_u32 count = 0;
|
|
while ((BOOTMGR_SAFE_MODE_ENTER_TOOGLE_MS * count++) < BOOTMGR_SAFE_MODE_ENTER_MS) {
|
|
// 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(BOOTMGR_SAFE_MODE_ENTER_TOOGLE_MS * 1000));
|
|
}
|
|
psBootInfo->ActiveImg = IMG_ACT_FACTORY;
|
|
// turn the led off
|
|
MAP_GPIOPinWrite(MICROPY_SYS_LED_PORT, MICROPY_SYS_LED_PORT_PIN, 0);
|
|
// request a safe boot to the application
|
|
PRCMRequestSafeBoot();
|
|
}
|
|
// do we have a new update image that needs to be verified?
|
|
else if ((psBootInfo->ActiveImg == IMG_ACT_UPDATE) && (psBootInfo->Status == IMG_STATUS_CHECK)) {
|
|
if (!bootmgr_verify()) {
|
|
// delete the corrupted file
|
|
sl_FsDel((_u8 *)IMG_UPDATE, 0);
|
|
// switch to the factory image
|
|
psBootInfo->ActiveImg = IMG_ACT_FACTORY;
|
|
}
|
|
// in any case, set the status as "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);
|
|
}
|
|
}
|
|
|
|
// now boot the active image
|
|
if (IMG_ACT_UPDATE == psBootInfo->ActiveImg) {
|
|
bootmgr_load_and_execute((unsigned char *)IMG_UPDATE);
|
|
}
|
|
else {
|
|
bootmgr_load_and_execute((unsigned char *)IMG_FACTORY);
|
|
}
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//! Main function
|
|
//*****************************************************************************
|
|
int main (void) {
|
|
sBootInfo_t sBootInfo = { .ActiveImg = IMG_ACT_FACTORY, .Status = IMG_STATUS_READY };
|
|
bool bootapp = false;
|
|
_i32 fhandle;
|
|
|
|
// Board Initialization
|
|
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);
|
|
}
|
|
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);
|
|
}
|
|
}
|
|
|
|
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 a fatal error 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, mp_uint_t *len) {
|
|
*len = 0;
|
|
return NULL;
|
|
}
|