main.c 13.3 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/*
 * 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>
30
31
32

#include "py/mpconfig.h"
#include MICROPY_HAL_H
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#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"
53
#include "debug.h"
54
#include "pybwdt.h"
55
#include "mperror.h"
56
57
58
59
60


//*****************************************************************************
// Local Constants
//*****************************************************************************
61
#define SL_STOP_TIMEOUT                     250
62
63
64
65
#define BOOTMGR_HASH_ALGO                   SHAMD5_ALGO_MD5
#define BOOTMGR_HASH_SIZE                   32
#define BOOTMGR_BUFF_SIZE                   512

66
67
#define BOOTMGR_WAIT_SAFE_MODE_MS           1600
#define BOOTMGR_WAIT_SAFE_MODE_TOOGLE_MS    200
68

69
70
#define BOOTMGR_SAFE_MODE_ENTER_MS          700
#define BOOTMGR_SAFE_MODE_ENTER_TOOGLE_MS   70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151

//*****************************************************************************
// 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();

152
153
    pybwdt_check_reset_cause();

154
155
156
    // Enable the Data Hashing Engine
    HASH_Init();

157
158
    // Init the system led and the system switch
    mperror_init0();
159

160
161
162
    // clear the safe boot request, since we should not trust
    // the register's state after reset
    mperror_clear_safe_boot();
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
}

//*****************************************************************************
//! 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;
244
245
    while (MAP_GPIOPinRead(MICROPY_SAFE_BOOT_PORT, MICROPY_SAFE_BOOT_PORT_PIN) &&
           ((BOOTMGR_WAIT_SAFE_MODE_TOOGLE_MS * count++) < BOOTMGR_WAIT_SAFE_MODE_MS)) {
246
        // toogle the led
247
        MAP_GPIOPinWrite(MICROPY_SYS_LED_PORT, MICROPY_SYS_LED_PORT_PIN, ~MAP_GPIOPinRead(MICROPY_SYS_LED_PORT, MICROPY_SYS_LED_PORT_PIN));
248
249
        UtilsDelay(UTILS_DELAY_US_TO_COUNT(BOOTMGR_WAIT_SAFE_MODE_TOOGLE_MS * 1000));
    }
250
251
    mperror_deinit_sfe_pin();
    return MAP_GPIOPinRead(MICROPY_SAFE_BOOT_PORT, MICROPY_SAFE_BOOT_PORT_PIN) ? true : false;
252
253
254
255
256
257
258
259
260
}

//*****************************************************************************
//! 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;
261
         while ((BOOTMGR_SAFE_MODE_ENTER_TOOGLE_MS * count++) < BOOTMGR_SAFE_MODE_ENTER_MS) {
262
             // toogle the led
263
             MAP_GPIOPinWrite(MICROPY_SYS_LED_PORT, MICROPY_SYS_LED_PORT_PIN, ~MAP_GPIOPinRead(MICROPY_SYS_LED_PORT, MICROPY_SYS_LED_PORT_PIN));
264
265
266
267
             UtilsDelay(UTILS_DELAY_US_TO_COUNT(BOOTMGR_SAFE_MODE_ENTER_TOOGLE_MS * 1000));
         }
         psBootInfo->ActiveImg = IMG_ACT_FACTORY;
         // turn the led off
268
269
270
         MAP_GPIOPinWrite(MICROPY_SYS_LED_PORT, MICROPY_SYS_LED_PORT_PIN, 0);
         // request a safe boot to the application
         mperror_request_safe_boot();
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
    }
    // 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
345
        MAP_GPIOPinWrite(MICROPY_SYS_LED_PORT, MICROPY_SYS_LED_PORT_PIN, MICROPY_SYS_LED_PORT_PIN);
346
347
348
349
350
351
        __asm volatile("    dsb      \n"
                       "    isb      \n"
                       "    wfi      \n");
    }
}