summaryrefslogtreecommitdiffstatshomepage
path: root/cc3200/bootmgr/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'cc3200/bootmgr/main.c')
-rw-r--r--cc3200/bootmgr/main.c355
1 files changed, 355 insertions, 0 deletions
diff --git a/cc3200/bootmgr/main.c b/cc3200/bootmgr/main.c
new file mode 100644
index 0000000000..ee8a32d347
--- /dev/null
+++ b/cc3200/bootmgr/main.c
@@ -0,0 +1,355 @@
+/*
+ * 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 "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"
+
+
+//*****************************************************************************
+// Local Constants
+//*****************************************************************************
+#define SL_STOP_TIMEOUT 500
+#define BOOTMGR_HASH_ALGO SHAMD5_ALGO_MD5
+#define BOOTMGR_HASH_SIZE 32
+#define BOOTMGR_BUFF_SIZE 512
+
+#define BOOTMGR_WAIT_SAFE_MODE_MS 2000
+#define BOOTMGR_WAIT_SAFE_MODE_TOOGLE_MS 250
+
+#define BOOTMGR_SAFE_MODE_ENTER_MS 1000
+#define BOOTMGR_SAFE_MODE_ENTER_TOOGLE_MS 100
+
+#define BOOTMGR_PINS_PRCM PRCM_GPIOA3
+#define BOOTMGR_PINS_PORT GPIOA3_BASE
+#define BOOTMGR_LED_PIN_NUM PIN_21
+#define BOOTMGR_SFE_PIN_NUM PIN_45
+#define BOOTMGR_LED_PORT_PIN GPIO_PIN_1 // GPIO25
+#define BOOTMGR_SFE_PORT_PIN GPIO_PIN_7 // GPIO31
+
+
+//*****************************************************************************
+// 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();
+
+ // Enable the Data Hashing Engine
+ HASH_Init();
+
+ // Enable GPIOA3 Peripheral Clock
+ MAP_PRCMPeripheralClkEnable(BOOTMGR_PINS_PRCM, PRCM_RUN_MODE_CLK);
+
+ // Configure the bld
+ MAP_PinTypeGPIO(BOOTMGR_LED_PIN_NUM, PIN_MODE_0, false);
+ MAP_PinConfigSet(BOOTMGR_LED_PIN_NUM, PIN_STRENGTH_6MA, PIN_TYPE_STD);
+ MAP_GPIODirModeSet(BOOTMGR_PINS_PORT, BOOTMGR_LED_PORT_PIN, GPIO_DIR_MODE_OUT);
+
+ // Configure the safe mode pin
+ MAP_PinTypeGPIO(BOOTMGR_SFE_PIN_NUM, PIN_MODE_0, false);
+ MAP_PinConfigSet(BOOTMGR_SFE_PIN_NUM, PIN_STRENGTH_6MA, PIN_TYPE_STD_PU);
+ MAP_GPIODirModeSet(BOOTMGR_PINS_PORT, BOOTMGR_SFE_PORT_PIN, GPIO_DIR_MODE_IN);
+}
+
+//*****************************************************************************
+//! 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(BOOTMGR_PINS_PORT, BOOTMGR_SFE_PORT_PIN) &&
+ ((BOOTMGR_WAIT_SAFE_MODE_TOOGLE_MS * count++) < BOOTMGR_WAIT_SAFE_MODE_MS)) {
+ // toogle the led
+ MAP_GPIOPinWrite(BOOTMGR_PINS_PORT, BOOTMGR_LED_PORT_PIN, ~MAP_GPIOPinRead(GPIOA3_BASE, BOOTMGR_LED_PORT_PIN));
+ UtilsDelay(UTILS_DELAY_US_TO_COUNT(BOOTMGR_WAIT_SAFE_MODE_TOOGLE_MS * 1000));
+ }
+ return MAP_GPIOPinRead(BOOTMGR_PINS_PORT, BOOTMGR_SFE_PORT_PIN) ? false : true;
+}
+
+//*****************************************************************************
+//! 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(BOOTMGR_PINS_PORT, BOOTMGR_LED_PORT_PIN, ~MAP_GPIOPinRead(GPIOA3_BASE, BOOTMGR_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(BOOTMGR_PINS_PORT, BOOTMGR_LED_PORT_PIN, 0);
+ }
+ // 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(NULL, NULL, NULL);
+
+ // 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(BOOTMGR_PINS_PORT, BOOTMGR_LED_PORT_PIN, BOOTMGR_LED_PORT_PIN);
+ __asm volatile(" dsb \n"
+ " isb \n"
+ " wfi \n");
+ }
+}
+