cc3200: Implement new OTA mechanism with 2 firmware update slots.
This commit is contained in:
parent
9309e609cd
commit
e955089da0
|
@ -19,6 +19,7 @@ BOOT_CPPDEFINES = -Dgcc -DBOOTLOADER -DTARGET_IS_CC3200 -DSL_TINY
|
||||||
BOOT_HAL_SRC_C = $(addprefix hal/,\
|
BOOT_HAL_SRC_C = $(addprefix hal/,\
|
||||||
cpu.c \
|
cpu.c \
|
||||||
interrupt.c \
|
interrupt.c \
|
||||||
|
gpio.c \
|
||||||
pin.c \
|
pin.c \
|
||||||
prcm.c \
|
prcm.c \
|
||||||
shamd5.c \
|
shamd5.c \
|
||||||
|
|
|
@ -43,7 +43,9 @@ extern "C"
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
#define IMG_BOOT_INFO "/sys/bootinfo.bin"
|
#define IMG_BOOT_INFO "/sys/bootinfo.bin"
|
||||||
#define IMG_FACTORY "/sys/factimg.bin"
|
#define IMG_FACTORY "/sys/factimg.bin"
|
||||||
#define IMG_UPDATE "/sys/updtimg.bin"
|
#define IMG_UPDATE1 "/sys/updtimg1.bin"
|
||||||
|
#define IMG_UPDATE2 "/sys/updtimg2.bin"
|
||||||
|
#define IMG_PREFIX "/sys/updtimg"
|
||||||
|
|
||||||
#define IMG_SRVPACK "/sys/servicepack.ucf"
|
#define IMG_SRVPACK "/sys/servicepack.ucf"
|
||||||
#define SRVPACK_SIGN "/sys/servicepack.sig"
|
#define SRVPACK_SIGN "/sys/servicepack.sig"
|
||||||
|
@ -55,7 +57,7 @@ extern "C"
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
Special file sizes
|
Special file sizes
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
#define IMG_SIZE (232 * 1024) /* 16KB are reserved for the bootloader and at least 8KB for the heap*/
|
#define IMG_SIZE (192 * 1024) /* 16KB are reserved for the bootloader and at least 48KB for the heap*/
|
||||||
#define SRVPACK_SIZE (16 * 1024)
|
#define SRVPACK_SIZE (16 * 1024)
|
||||||
#define SIGN_SIZE (2 * 1024)
|
#define SIGN_SIZE (2 * 1024)
|
||||||
#define CA_KEY_SIZE (4 * 1024)
|
#define CA_KEY_SIZE (4 * 1024)
|
||||||
|
@ -64,7 +66,8 @@ extern "C"
|
||||||
Active Image
|
Active Image
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
#define IMG_ACT_FACTORY 0
|
#define IMG_ACT_FACTORY 0
|
||||||
#define IMG_ACT_UPDATE 1
|
#define IMG_ACT_UPDATE1 1
|
||||||
|
#define IMG_ACT_UPDATE2 2
|
||||||
|
|
||||||
#define IMG_STATUS_CHECK 0
|
#define IMG_STATUS_CHECK 0
|
||||||
#define IMG_STATUS_READY 1
|
#define IMG_STATUS_READY 1
|
||||||
|
@ -72,13 +75,13 @@ extern "C"
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
Boot Info structure
|
Boot Info structure
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
typedef struct sBootInfo
|
typedef struct _sBootInfo_t
|
||||||
{
|
{
|
||||||
_u8 ActiveImg;
|
_u8 ActiveImg;
|
||||||
_u8 Status;
|
_u8 Status;
|
||||||
|
_u8 PrevImg;
|
||||||
_u8 : 8;
|
_u8 : 8;
|
||||||
_u8 : 8;
|
} sBootInfo_t;
|
||||||
}sBootInfo_t;
|
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
|
|
|
@ -64,11 +64,14 @@
|
||||||
#define BOOTMGR_HASH_SIZE 32
|
#define BOOTMGR_HASH_SIZE 32
|
||||||
#define BOOTMGR_BUFF_SIZE 512
|
#define BOOTMGR_BUFF_SIZE 512
|
||||||
|
|
||||||
#define BOOTMGR_WAIT_SAFE_MODE_MS 2400
|
#define BOOTMGR_WAIT_SAFE_MODE_0_MS 3000
|
||||||
#define BOOTMGR_WAIT_SAFE_MODE_TOOGLE_MS 400
|
#define BOOTMGR_WAIT_SAFE_MODE_0_BLINK_MS 500
|
||||||
|
|
||||||
#define BOOTMGR_SAFE_MODE_ENTER_MS 1600
|
#define BOOTMGR_WAIT_SAFE_MODE_1_MS 3000
|
||||||
#define BOOTMGR_SAFE_MODE_ENTER_TOOGLE_MS 160
|
#define BOOTMGR_WAIT_SAFE_MODE_1_BLINK_MS 250
|
||||||
|
|
||||||
|
#define BOOTMGR_WAIT_SAFE_MODE_2_MS 1500
|
||||||
|
#define BOOTMGR_WAIT_SAFE_MODE_2_BLINK_MS 100
|
||||||
|
|
||||||
//*****************************************************************************
|
//*****************************************************************************
|
||||||
// Exported functions declarations
|
// Exported functions declarations
|
||||||
|
@ -79,9 +82,10 @@ extern void bootmgr_run_app (_u32 base);
|
||||||
// Local functions declarations
|
// Local functions declarations
|
||||||
//*****************************************************************************
|
//*****************************************************************************
|
||||||
static void bootmgr_board_init (void);
|
static void bootmgr_board_init (void);
|
||||||
static bool bootmgr_verify (void);
|
static bool bootmgr_verify (_u8 *image);
|
||||||
static void bootmgr_load_and_execute (_u8 *image);
|
static void bootmgr_load_and_execute (_u8 *image);
|
||||||
static bool safe_mode_boot (void);
|
static bool wait_while_blinking (uint32_t wait_time, uint32_t period, bool force_wait);
|
||||||
|
static void wait_for_safe_boot (sBootInfo_t *psBootInfo);
|
||||||
static void bootmgr_image_loader (sBootInfo_t *psBootInfo);
|
static void bootmgr_image_loader (sBootInfo_t *psBootInfo);
|
||||||
|
|
||||||
//*****************************************************************************
|
//*****************************************************************************
|
||||||
|
@ -140,14 +144,14 @@ void SimpleLinkSockEventHandler(SlSockEvent_t *pSock)
|
||||||
//! Board Initialization & Configuration
|
//! Board Initialization & Configuration
|
||||||
//*****************************************************************************
|
//*****************************************************************************
|
||||||
static void bootmgr_board_init(void) {
|
static void bootmgr_board_init(void) {
|
||||||
// Set vector table base
|
// set the vector table base
|
||||||
MAP_IntVTableBaseSet((unsigned long)&g_pfnVectors[0]);
|
MAP_IntVTableBaseSet((unsigned long)&g_pfnVectors[0]);
|
||||||
|
|
||||||
// Enable Processor Interrupts
|
// enable processor interrupts
|
||||||
MAP_IntMasterEnable();
|
MAP_IntMasterEnable();
|
||||||
MAP_IntEnable(FAULT_SYSTICK);
|
MAP_IntEnable(FAULT_SYSTICK);
|
||||||
|
|
||||||
// Mandatory MCU Initialization
|
// mandatory MCU initialization
|
||||||
PRCMCC3200MCUInit();
|
PRCMCC3200MCUInit();
|
||||||
|
|
||||||
mperror_bootloader_check_reset_cause();
|
mperror_bootloader_check_reset_cause();
|
||||||
|
@ -157,10 +161,10 @@ static void bootmgr_board_init(void) {
|
||||||
antenna_init0();
|
antenna_init0();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Enable the Data Hashing Engine
|
// enable the data hashing engine
|
||||||
CRYPTOHASH_Init();
|
CRYPTOHASH_Init();
|
||||||
|
|
||||||
// Init the system led and the system switch
|
// init the system led and the system switch
|
||||||
mperror_init0();
|
mperror_init0();
|
||||||
|
|
||||||
// clear the safe boot flag, since we can't trust its content after reset
|
// clear the safe boot flag, since we can't trust its content after reset
|
||||||
|
@ -170,15 +174,15 @@ static void bootmgr_board_init(void) {
|
||||||
//*****************************************************************************
|
//*****************************************************************************
|
||||||
//! Verifies the integrity of the new application binary
|
//! Verifies the integrity of the new application binary
|
||||||
//*****************************************************************************
|
//*****************************************************************************
|
||||||
static bool bootmgr_verify (void) {
|
static bool bootmgr_verify (_u8 *image) {
|
||||||
SlFsFileInfo_t FsFileInfo;
|
SlFsFileInfo_t FsFileInfo;
|
||||||
_u32 reqlen, offset = 0;
|
_u32 reqlen, offset = 0;
|
||||||
_i32 fHandle;
|
_i32 fHandle;
|
||||||
|
|
||||||
// open the file for reading
|
// open the file for reading
|
||||||
if (0 == sl_FsOpen((_u8 *)IMG_UPDATE, FS_MODE_OPEN_READ, NULL, &fHandle)) {
|
if (0 == sl_FsOpen(image, FS_MODE_OPEN_READ, NULL, &fHandle)) {
|
||||||
// get the file size
|
// get the file size
|
||||||
sl_FsGetInfo((_u8 *)IMG_UPDATE, 0, &FsFileInfo);
|
sl_FsGetInfo(image, 0, &FsFileInfo);
|
||||||
|
|
||||||
if (FsFileInfo.FileLen > BOOTMGR_HASH_SIZE) {
|
if (FsFileInfo.FileLen > BOOTMGR_HASH_SIZE) {
|
||||||
FsFileInfo.FileLen -= BOOTMGR_HASH_SIZE;
|
FsFileInfo.FileLen -= BOOTMGR_HASH_SIZE;
|
||||||
|
@ -242,47 +246,72 @@ static void bootmgr_load_and_execute (_u8 *image) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//*****************************************************************************
|
//*****************************************************************************
|
||||||
//! Check for the safe mode pin
|
//! Wait while the safe mode pin is being held high and blink the system led
|
||||||
|
//! with the specified period
|
||||||
//*****************************************************************************
|
//*****************************************************************************
|
||||||
static bool safe_mode_boot (void) {
|
static bool wait_while_blinking (uint32_t wait_time, uint32_t period, bool force_wait) {
|
||||||
_u32 count = 0;
|
_u32 count;
|
||||||
while (MAP_GPIOPinRead(MICROPY_SAFE_BOOT_PORT, MICROPY_SAFE_BOOT_PORT_PIN) &&
|
for (count = 0; (force_wait || MAP_GPIOPinRead(MICROPY_SAFE_BOOT_PORT, MICROPY_SAFE_BOOT_PORT_PIN)) &&
|
||||||
((BOOTMGR_WAIT_SAFE_MODE_TOOGLE_MS * count++) < BOOTMGR_WAIT_SAFE_MODE_MS)) {
|
((period * count) < wait_time); count++) {
|
||||||
// toogle the led
|
// 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));
|
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));
|
UtilsDelay(UTILS_DELAY_US_TO_COUNT(period * 1000));
|
||||||
}
|
}
|
||||||
mperror_deinit_sfe_pin();
|
|
||||||
return MAP_GPIOPinRead(MICROPY_SAFE_BOOT_PORT, MICROPY_SAFE_BOOT_PORT_PIN) ? true : false;
|
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.
|
//! Check for the safe mode pin
|
||||||
//*****************************************************************************
|
//*****************************************************************************
|
||||||
static void bootmgr_image_loader(sBootInfo_t *psBootInfo) {
|
static void wait_for_safe_boot (sBootInfo_t *psBootInfo) {
|
||||||
_i32 fhandle;
|
if (wait_while_blinking(BOOTMGR_WAIT_SAFE_MODE_0_MS, BOOTMGR_WAIT_SAFE_MODE_0_BLINK_MS, false)) {
|
||||||
if (safe_mode_boot()) {
|
// go back one step in time
|
||||||
_u32 count = 0;
|
psBootInfo->ActiveImg = psBootInfo->PrevImg;
|
||||||
while ((BOOTMGR_SAFE_MODE_ENTER_TOOGLE_MS * count++) < BOOTMGR_SAFE_MODE_ENTER_MS) {
|
if (wait_while_blinking(BOOTMGR_WAIT_SAFE_MODE_1_MS, BOOTMGR_WAIT_SAFE_MODE_1_BLINK_MS, false)) {
|
||||||
// toogle the led
|
// go back directly to the factory image
|
||||||
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;
|
psBootInfo->ActiveImg = IMG_ACT_FACTORY;
|
||||||
// turn the led off
|
wait_while_blinking(BOOTMGR_WAIT_SAFE_MODE_2_MS, BOOTMGR_WAIT_SAFE_MODE_2_BLINK_MS, true);
|
||||||
|
}
|
||||||
|
// turn off the system led
|
||||||
MAP_GPIOPinWrite(MICROPY_SYS_LED_PORT, MICROPY_SYS_LED_PORT_PIN, 0);
|
MAP_GPIOPinWrite(MICROPY_SYS_LED_PORT, MICROPY_SYS_LED_PORT_PIN, 0);
|
||||||
// request a safe boot to the application
|
// request a safe boot to the application
|
||||||
PRCMRequestSafeBoot();
|
PRCMRequestSafeBoot();
|
||||||
}
|
}
|
||||||
// do we have a new update image that needs to be verified?
|
// uninit the safe boot pin
|
||||||
else if ((psBootInfo->ActiveImg == IMG_ACT_UPDATE) && (psBootInfo->Status == IMG_STATUS_CHECK)) {
|
mperror_deinit_sfe_pin();
|
||||||
if (!bootmgr_verify()) {
|
}
|
||||||
// delete the corrupted file
|
|
||||||
sl_FsDel((_u8 *)IMG_UPDATE, 0);
|
//*****************************************************************************
|
||||||
// switch to the factory image
|
//! Load the proper image based on the information from the boot info
|
||||||
psBootInfo->ActiveImg = IMG_ACT_FACTORY;
|
//! 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;
|
||||||
}
|
}
|
||||||
// in any case, set the status as "READY"
|
|
||||||
|
// 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;
|
psBootInfo->Status = IMG_STATUS_READY;
|
||||||
// write the new boot info
|
// write the new boot info
|
||||||
if (!sl_FsOpen((unsigned char *)IMG_BOOT_INFO, FS_MODE_OPEN_WRITE, NULL, &fhandle)) {
|
if (!sl_FsOpen((unsigned char *)IMG_BOOT_INFO, FS_MODE_OPEN_WRITE, NULL, &fhandle)) {
|
||||||
|
@ -292,24 +321,34 @@ static void bootmgr_image_loader(sBootInfo_t *psBootInfo) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// now boot the active image
|
// this one might modify the boot info hence it MUST be called after
|
||||||
if (IMG_ACT_UPDATE == psBootInfo->ActiveImg) {
|
// bootmgr_verify! (so that the changes are not saved to flash)
|
||||||
bootmgr_load_and_execute((unsigned char *)IMG_UPDATE);
|
wait_for_safe_boot(psBootInfo);
|
||||||
}
|
|
||||||
else {
|
// select the active image again, since it might have changed
|
||||||
bootmgr_load_and_execute((unsigned char *)IMG_FACTORY);
|
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
|
//! Main function
|
||||||
//*****************************************************************************
|
//*****************************************************************************
|
||||||
int main (void) {
|
int main (void) {
|
||||||
sBootInfo_t sBootInfo = { .ActiveImg = IMG_ACT_FACTORY, .Status = IMG_STATUS_READY };
|
sBootInfo_t sBootInfo = { .ActiveImg = IMG_ACT_FACTORY, .Status = IMG_STATUS_READY, .PrevImg = IMG_ACT_FACTORY };
|
||||||
bool bootapp = false;
|
bool bootapp = false;
|
||||||
_i32 fhandle;
|
_i32 fhandle;
|
||||||
|
|
||||||
// Board Initialization
|
// board setup
|
||||||
bootmgr_board_init();
|
bootmgr_board_init();
|
||||||
|
|
||||||
// start simplelink since we need it to access the sflash
|
// start simplelink since we need it to access the sflash
|
||||||
|
@ -322,12 +361,13 @@ int main (void) {
|
||||||
}
|
}
|
||||||
sl_FsClose(fhandle, 0, 0, 0);
|
sl_FsClose(fhandle, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
// boot info file not present (or read failed)
|
||||||
if (!bootapp) {
|
if (!bootapp) {
|
||||||
// create a new boot info file
|
// create a new boot info file
|
||||||
_u32 BootInfoCreateFlag = _FS_FILE_OPEN_FLAG_COMMIT | _FS_FILE_PUBLIC_WRITE | _FS_FILE_PUBLIC_READ;
|
_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)),
|
if (!sl_FsOpen ((unsigned char *)IMG_BOOT_INFO, FS_MODE_OPEN_CREATE((2 * sizeof(sBootInfo_t)),
|
||||||
BootInfoCreateFlag), NULL, &fhandle)) {
|
BootInfoCreateFlag), NULL, &fhandle)) {
|
||||||
// Write the default boot info.
|
// write the default boot info.
|
||||||
if (sizeof(sBootInfo_t) == sl_FsWrite(fhandle, 0, (unsigned char *)&sBootInfo, sizeof(sBootInfo_t))) {
|
if (sizeof(sBootInfo_t) == sl_FsWrite(fhandle, 0, (unsigned char *)&sBootInfo, sizeof(sBootInfo_t))) {
|
||||||
bootapp = true;
|
bootapp = true;
|
||||||
}
|
}
|
||||||
|
@ -343,8 +383,8 @@ int main (void) {
|
||||||
// stop simplelink
|
// stop simplelink
|
||||||
sl_Stop(SL_STOP_TIMEOUT);
|
sl_Stop(SL_STOP_TIMEOUT);
|
||||||
|
|
||||||
// if we've reached this point, then it means a fatal error occurred and the application
|
// if we've reached this point, then it means that a fatal error has occurred and the
|
||||||
// could not be loaded, so, loop forever and signal the crash to the user
|
// application could not be loaded, so, loop forever and signal the crash to the user
|
||||||
while (true) {
|
while (true) {
|
||||||
// keep the bld on
|
// keep the bld on
|
||||||
MAP_GPIOPinWrite(MICROPY_SYS_LED_PORT, MICROPY_SYS_LED_PORT_PIN, MICROPY_SYS_LED_PORT_PIN);
|
MAP_GPIOPinWrite(MICROPY_SYS_LED_PORT, MICROPY_SYS_LED_PORT_PIN, MICROPY_SYS_LED_PORT_PIN);
|
||||||
|
|
|
@ -764,6 +764,8 @@ static void ftp_process_cmd (void) {
|
||||||
ftp_send_reply(150, NULL);
|
ftp_send_reply(150, NULL);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
// to unlock the updater
|
||||||
|
updater_finnish();
|
||||||
ftp_data.state = E_FTP_STE_END_TRANSFER;
|
ftp_data.state = E_FTP_STE_END_TRANSFER;
|
||||||
ftp_send_reply(550, NULL);
|
ftp_send_reply(550, NULL);
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
#include "modnetwork.h"
|
#include "modnetwork.h"
|
||||||
#include "modwlan.h"
|
#include "modwlan.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
#include "osi.h"
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
DEFINE PRIVATE CONSTANTS
|
DEFINE PRIVATE CONSTANTS
|
||||||
|
@ -61,15 +62,37 @@ typedef struct {
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
DECLARE PRIVATE DATA
|
DECLARE PRIVATE DATA
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
static updater_data_t updater_data;
|
static updater_data_t updater_data = { .path = NULL, .fhandle = -1, .fsize = 0, .foffset = 0 };
|
||||||
|
static OsiLockObj_t updater_LockObj;
|
||||||
|
static sBootInfo_t sBootInfo;
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
DEFINE PUBLIC FUNCTIONS
|
DEFINE PUBLIC FUNCTIONS
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
__attribute__ ((section (".boot")))
|
||||||
|
void updater_pre_init (void) {
|
||||||
|
// create the updater lock
|
||||||
|
ASSERT(OSI_OK == sl_LockObjCreate(&updater_LockObj, "UpdaterLock"));
|
||||||
|
}
|
||||||
|
|
||||||
bool updater_check_path (void *path) {
|
bool updater_check_path (void *path) {
|
||||||
|
sl_LockObjLock (&updater_LockObj, SL_OS_WAIT_FOREVER);
|
||||||
if (!strcmp(UPDATER_IMG_PATH, path)) {
|
if (!strcmp(UPDATER_IMG_PATH, path)) {
|
||||||
updater_data.path = IMG_UPDATE;
|
|
||||||
updater_data.fsize = IMG_SIZE;
|
updater_data.fsize = IMG_SIZE;
|
||||||
|
updater_data.path = IMG_UPDATE1;
|
||||||
|
// the launchxl doesn't have enough flash space for 2 user update images
|
||||||
|
#ifdef WIPY
|
||||||
|
// check which one should be the next active image
|
||||||
|
_i32 fhandle;
|
||||||
|
if (!sl_FsOpen((unsigned char *)IMG_BOOT_INFO, FS_MODE_OPEN_READ, NULL, &fhandle)) {
|
||||||
|
ASSERT (sizeof(sBootInfo_t) == sl_FsRead(fhandle, 0, (unsigned char *)&sBootInfo, sizeof(sBootInfo_t)));
|
||||||
|
sl_FsClose(fhandle, 0, 0, 0);
|
||||||
|
if ((sBootInfo.Status == IMG_STATUS_CHECK && sBootInfo.ActiveImg == IMG_ACT_UPDATE2) ||
|
||||||
|
sBootInfo.ActiveImg == IMG_ACT_UPDATE1) {
|
||||||
|
updater_data.path = IMG_UPDATE2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
} else if (!strcmp(UPDATER_SRVPACK_PATH, path)) {
|
} else if (!strcmp(UPDATER_SRVPACK_PATH, path)) {
|
||||||
updater_data.path = IMG_SRVPACK;
|
updater_data.path = IMG_SRVPACK;
|
||||||
updater_data.fsize = SRVPACK_SIZE;
|
updater_data.fsize = SRVPACK_SIZE;
|
||||||
|
@ -86,6 +109,7 @@ bool updater_check_path (void *path) {
|
||||||
updater_data.path = KEY_FILE;
|
updater_data.path = KEY_FILE;
|
||||||
updater_data.fsize = CA_KEY_SIZE;
|
updater_data.fsize = CA_KEY_SIZE;
|
||||||
} else {
|
} else {
|
||||||
|
sl_LockObjUnlock (&updater_LockObj);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -106,7 +130,6 @@ bool updater_start (void) {
|
||||||
result = true;
|
result = true;
|
||||||
}
|
}
|
||||||
sl_LockObjUnlock (&wlan_LockObj);
|
sl_LockObjUnlock (&wlan_LockObj);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,35 +147,56 @@ bool updater_write (uint8_t *buf, uint32_t len) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void updater_finnish (void) {
|
void updater_finnish (void) {
|
||||||
sBootInfo_t sBootInfo;
|
|
||||||
_i32 fhandle;
|
_i32 fhandle;
|
||||||
|
|
||||||
if (updater_data.fhandle > 0) {
|
if (updater_data.fhandle > 0) {
|
||||||
sl_LockObjLock (&wlan_LockObj, SL_OS_WAIT_FOREVER);
|
sl_LockObjLock (&wlan_LockObj, SL_OS_WAIT_FOREVER);
|
||||||
// close the file being updated
|
// close the file being updated
|
||||||
sl_FsClose(updater_data.fhandle, NULL, NULL, 0);
|
sl_FsClose(updater_data.fhandle, NULL, NULL, 0);
|
||||||
|
#ifdef WIPY
|
||||||
if (!strcmp (IMG_UPDATE, updater_data.path)) {
|
// if we still have an image pending for verification, leave the boot info as it is
|
||||||
// open the boot info file for reading
|
if (!strncmp(IMG_PREFIX, updater_data.path, strlen(IMG_PREFIX)) && sBootInfo.Status != IMG_STATUS_CHECK) {
|
||||||
|
#else
|
||||||
|
if (!strncmp(IMG_PREFIX, updater_data.path, strlen(IMG_PREFIX))) {
|
||||||
|
#endif
|
||||||
|
#ifdef DEBUG
|
||||||
if (!sl_FsOpen((unsigned char *)IMG_BOOT_INFO, FS_MODE_OPEN_READ, NULL, &fhandle)) {
|
if (!sl_FsOpen((unsigned char *)IMG_BOOT_INFO, FS_MODE_OPEN_READ, NULL, &fhandle)) {
|
||||||
|
|
||||||
ASSERT (sizeof(sBootInfo_t) == sl_FsRead(fhandle, 0, (unsigned char *)&sBootInfo, sizeof(sBootInfo_t)));
|
ASSERT (sizeof(sBootInfo_t) == sl_FsRead(fhandle, 0, (unsigned char *)&sBootInfo, sizeof(sBootInfo_t)));
|
||||||
sl_FsClose(fhandle, 0, 0, 0);
|
sl_FsClose(fhandle, 0, 0, 0);
|
||||||
// open the file for writing
|
#endif
|
||||||
|
// open the boot info file for writing
|
||||||
ASSERT (sl_FsOpen((unsigned char *)IMG_BOOT_INFO, FS_MODE_OPEN_WRITE, NULL, &fhandle) == 0);
|
ASSERT (sl_FsOpen((unsigned char *)IMG_BOOT_INFO, FS_MODE_OPEN_WRITE, NULL, &fhandle) == 0);
|
||||||
|
#ifdef DEBUG
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
// the boot info file doesn't exist yet
|
||||||
_u32 BootInfoCreateFlag = _FS_FILE_OPEN_FLAG_COMMIT | _FS_FILE_PUBLIC_WRITE | _FS_FILE_PUBLIC_READ;
|
_u32 BootInfoCreateFlag = _FS_FILE_OPEN_FLAG_COMMIT | _FS_FILE_PUBLIC_WRITE | _FS_FILE_PUBLIC_READ;
|
||||||
ASSERT (sl_FsOpen ((unsigned char *)IMG_BOOT_INFO, FS_MODE_OPEN_CREATE((2 * sizeof(sBootInfo_t)),
|
ASSERT (sl_FsOpen ((unsigned char *)IMG_BOOT_INFO, FS_MODE_OPEN_CREATE((2 * sizeof(sBootInfo_t)),
|
||||||
BootInfoCreateFlag), NULL, &fhandle) == 0);
|
BootInfoCreateFlag), NULL, &fhandle) == 0);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// write the new boot info
|
// save the new boot info
|
||||||
sBootInfo.ActiveImg = IMG_ACT_UPDATE;
|
#ifdef WIPY
|
||||||
|
sBootInfo.PrevImg = sBootInfo.ActiveImg;
|
||||||
|
if (sBootInfo.ActiveImg == IMG_ACT_UPDATE1) {
|
||||||
|
sBootInfo.ActiveImg = IMG_ACT_UPDATE2;
|
||||||
|
} else {
|
||||||
|
sBootInfo.ActiveImg = IMG_ACT_UPDATE1;
|
||||||
|
}
|
||||||
|
// the launchxl doesn't have enough flash space for 2 user updates
|
||||||
|
#else
|
||||||
|
sBootInfo.PrevImg = IMG_ACT_FACTORY;
|
||||||
|
sBootInfo.ActiveImg = IMG_ACT_UPDATE1;
|
||||||
|
#endif
|
||||||
sBootInfo.Status = IMG_STATUS_CHECK;
|
sBootInfo.Status = IMG_STATUS_CHECK;
|
||||||
ASSERT (sizeof(sBootInfo_t) == sl_FsWrite(fhandle, 0, (unsigned char *)&sBootInfo, sizeof(sBootInfo_t)));
|
ASSERT (sizeof(sBootInfo_t) == sl_FsWrite(fhandle, 0, (unsigned char *)&sBootInfo, sizeof(sBootInfo_t)));
|
||||||
sl_FsClose(fhandle, 0, 0, 0);
|
sl_FsClose(fhandle, 0, 0, 0);
|
||||||
}
|
}
|
||||||
sl_LockObjUnlock (&wlan_LockObj);
|
sl_LockObjUnlock (&wlan_LockObj);
|
||||||
}
|
|
||||||
updater_data.fhandle = -1;
|
updater_data.fhandle = -1;
|
||||||
|
}
|
||||||
|
sl_LockObjUnlock (&updater_LockObj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,10 +28,11 @@
|
||||||
#ifndef UPDATER_H_
|
#ifndef UPDATER_H_
|
||||||
#define UPDATER_H_
|
#define UPDATER_H_
|
||||||
|
|
||||||
bool updater_check_path (void *path);
|
extern void updater_pre_init (void);
|
||||||
bool updater_start (void);
|
extern bool updater_check_path (void *path);
|
||||||
bool updater_write (uint8_t *buf, uint32_t len);
|
extern bool updater_start (void);
|
||||||
void updater_finnish (void);
|
extern bool updater_write (uint8_t *buf, uint32_t len);
|
||||||
bool updater_verify (uint8_t *rbuff, uint8_t *hasbuff);
|
extern void updater_finnish (void);
|
||||||
|
extern bool updater_verify (uint8_t *rbuff, uint8_t *hasbuff);
|
||||||
|
|
||||||
#endif /* UPDATER_H_ */
|
#endif /* UPDATER_H_ */
|
||||||
|
|
|
@ -67,6 +67,7 @@
|
||||||
#include "pybtimer.h"
|
#include "pybtimer.h"
|
||||||
#include "mpcallback.h"
|
#include "mpcallback.h"
|
||||||
#include "cryptohash.h"
|
#include "cryptohash.h"
|
||||||
|
#include "updater.h"
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
DECLARE PRIVATE CONSTANTS
|
DECLARE PRIVATE CONSTANTS
|
||||||
|
@ -279,6 +280,9 @@ STATIC void mptask_pre_init (void) {
|
||||||
// this one allocates memory for the WLAN semaphore
|
// this one allocates memory for the WLAN semaphore
|
||||||
wlan_pre_init();
|
wlan_pre_init();
|
||||||
|
|
||||||
|
// this one allocates memory for the updater semaphore
|
||||||
|
updater_pre_init();
|
||||||
|
|
||||||
// this one allocates memory for the Socket semaphore
|
// this one allocates memory for the Socket semaphore
|
||||||
modusocket_pre_init();
|
modusocket_pre_init();
|
||||||
|
|
||||||
|
|
|
@ -32,15 +32,35 @@ Boot modes
|
||||||
----------
|
----------
|
||||||
|
|
||||||
If you power up normally, or press the reset button, the WiPy will boot
|
If you power up normally, or press the reset button, the WiPy will boot
|
||||||
into standard mode: the ``boot.py`` file will be executed first, then
|
into standard mode; the ``boot.py`` file will be executed first, then
|
||||||
``main.py`` will run.
|
``main.py`` will run.
|
||||||
|
|
||||||
You can override this boot sequence by pulling ``GPIO28`` **up** (connect
|
You can override this boot sequence by pulling ``GPIO28`` **up** (connect
|
||||||
it to the 3v3 output pin) during reset. The heart beat LED will flash slowly
|
it to the 3v3 output pin) during reset. This procedure also allows going
|
||||||
3 times to signal that safe boot is being requested, and then 4 more times
|
back in time to old firmware versions. The WiPy can hold up to 3 different
|
||||||
quickly to let you know that safe boot is going to be performed. While safe
|
firmware versions, which are: the factory firmware plus 2 user updates.
|
||||||
booting, the WiPy runs the factory firmware and skips the execution of
|
|
||||||
``boot.py`` and ``main.py``. This is useful to recover from any crash situation.
|
After reset, if ``GPIO28`` is held high, the heart beat LED will start flashing
|
||||||
|
slowly, if after 3 seconds the pin is still being held high, the LED will start
|
||||||
|
blinking a bit faster and the WiPy will select the previous user update to boot.
|
||||||
|
If the previous user update is the desired firmware image, ``GPIO28`` must be
|
||||||
|
released before 3 more seconds elapse. If 3 seconds later the pin is still high,
|
||||||
|
the factory firmware will be selected, the LED will flash quickly for 1.5 seconds
|
||||||
|
and the WiPy will proceed to boot. The firmware selection mechanism is as follows:
|
||||||
|
|
||||||
|
|
||||||
|
**Safe Boot Pin** ``GPIO28`` **released during:**
|
||||||
|
|
||||||
|
+-------------------------+-------------------------+----------------------------+
|
||||||
|
| 1st 3 secs window | 2nd 3 secs window | Final 1.5 secs window |
|
||||||
|
+=========================+=========================+============================+
|
||||||
|
| | Normal boot, *latest* | | Safe boot, *previous* | | Safe boot, the *factory* |
|
||||||
|
| | firmware is selected | | user update selected | | firmware is selected |
|
||||||
|
+-------------------------+-------------------------+----------------------------+
|
||||||
|
|
||||||
|
When selecting a previous firmware version, safe boot mode is entered, meaning
|
||||||
|
that the execution of both ``boot.py`` and ``main.py`` is skipped. This is
|
||||||
|
useful to recover from crash situations caused by the user scripts.
|
||||||
|
|
||||||
The heart beat LED
|
The heart beat LED
|
||||||
------------------
|
------------------
|
||||||
|
|
Loading…
Reference in New Issue