test
Dependencies: BMI160 max32630hsp3 MemoryLCD USBDevice
Diff: bootloader/bootldrAPI.cpp
- Revision:
- 0:ac4dea3e2894
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bootloader/bootldrAPI.cpp Mon Mar 18 10:21:53 2019 +0300 @@ -0,0 +1,651 @@ +/* + * bootldrInterface.cpp + * + * Created on: Feb 7, 2019 + * Author: Yagmur.Gok + */ + +#include <mbed.h> /*for type definitions*/ +#include "bootldrAPI.h" +#include "SHComm.h" +#include "demoDefinitions.h" + +//extern Serial daplink; + +//#define SERIALOUT printf +//#define SERIALIN printf + +#define COMM_SUCCESS 0 +#define COMM_GENERAL_ERROR -1 +#define COMM_INVALID_PARAM -254 +#define COMM_NOT_RECOGNIZED -255 + +#define BL_FLASH_ERR_GENERAL -1 +#define BL_FLASH_ERR_CHECKSUM -2 +#define BL_FLASH_ERR_AUTH -3 +#define BL_SET_NUM_PAGES_FAIL -4 +#define BL_FLASS_ERASE_FAIL -5 +#define BL_SET_IV_FAIL -6 +#define BL_FLASHING_FAIL -7 +#define BL_RAM_ALLOC_FAIL -8 + +#define AES_NONCE_SIZE 11 +#define AES_AUTH_SIZE 16 +#define BOOTLOADER_MAX_PAGE_SIZE (8192) +#define CHECKBYTES_SIZE (16) +#define FLASHCMDBYTES (2) + +#define SS_BOOTLOADER_ERASE_DELAY 700 +#define AES_NONCE_SIZE 11 +#define AES_AUTH_SIZE 16 +#define MAX_PAGE_SIZE 8192 +#define CHECKBYTES_SIZE 16 + +#define PAGE_WRITE_DELAY_MS 170 +#define MAX_PAGE_NUMBER 31 +#define PAGE_ERASE_CMD_SLEEP_MS 50 +#define BL_CFG_SAVE_CMD_SLEEP_MS 50 + +static int parse_iv(const char* cmd, uint8_t* iv_bytes); +static int parse_auth(const char* cmd, uint8_t *auth_bytes); +static int is_hub_ready_for_flash(void); +static void clear_state_info(void); + + +typedef struct { + int num_allocated_pages; /* Allocated page size */ + int num_pages; + int num_received_pages; + int page_size; + uint8_t auth[AES_AUTH_SIZE]; + uint8_t nonce[AES_NONCE_SIZE]; + uint8_t pages[MAX_PAGE_NUMBER * (MAX_PAGE_SIZE + CHECKBYTES_SIZE)]; //TODO: Use dynamic allocation +} app_image_t; + + +static app_image_t *app_image = NULL; + +static struct { + + uint32_t num_pages; + uint32_t page_size; + uint32_t hub_mode_bootloader; + uint32_t is_iv_set; + uint32_t is_auth_done; + uint32_t is_flash_erased; + uint32_t flag_image_on_ram; + uint32_t bootcmds_delay_factor; + uint32_t ebl_mode; + +}bootldrState = { 0 , 0 , 0 ,0 , 0 , 0 , 0 , 1 ,1}; + + + +int BOOTLDR_get_host_bootloader_state(const char *null_arg){ + + SERIALOUT(" \r\n BOOT STATE INFO: \r\n num_pages= %d \r\n page_size= %d \r\n is_iv_set= %d \r\n is_auth_done= %d \r\n is_flash_erased= %d \r\n flag_image_on_ram= %d \r\n bootcmds_delay_factor= %d \r\n ebl_mode= %d \r\n", + bootldrState.num_pages, + bootldrState.page_size, + bootldrState.is_iv_set, + bootldrState.is_auth_done, + bootldrState.is_flash_erased, + bootldrState.flag_image_on_ram, + bootldrState.bootcmds_delay_factor, + bootldrState.ebl_mode ); + + +} + +int SH_BOOTLDR_enter_blmode(const char *null_arg){ + + int status = 0x00; + + //status = sh_put_in_bootloader(); + //status = sh_set_ebl_mode((uint8_t)1); /* 1: GPIO rest 0: CMD reset*/ + + if( status == 0x00) { + + //////////status = sh_reset_to_bootloader(); - CHECKIF PROBLEM STILL PRESENT!! + status = sh_debug_reset_to_bootloader(); + //status = sh_set_sensorhub_operating_mode((uint8_t)0x08); + if (status == 0x00) { + SERIALOUT("\r\n%s err=%d\r\n", "bootldr", COMM_SUCCESS); + bootldrState.hub_mode_bootloader = 1; + } + else + SERIALOUT("\r\n%s err=%d\r\n", "bootldr", COMM_GENERAL_ERROR); + } + + return status; + +} + + +int SH_BOOTLDR_exit_blmode(const char *null_arg){ + + int status; + status = sh_reset_to_main_app() ; //sh_exit_from_bootloader(); + if (status == 0x00) + printf("\r\n exited from bootloader mode \r\n"); + + if (status == 0x00) { + SERIALOUT("\r\n%s err=%d\r\n", "exit", COMM_SUCCESS); + bootldrState.hub_mode_bootloader = 0; + } + else + SERIALOUT("\r\n%s err=%d\r\n", "exit", COMM_GENERAL_ERROR); + + return status; + +} + +int SH_BOOTLOADER_image_on_ram( const char *arg ){ + + int status = COMM_SUCCESS; + int tmp; + sscanf(arg, "%*s %d", &tmp ); + bootldrState.flag_image_on_ram = (tmp > 0)? 1:0 ; + + if(tmp == 1){ + + app_image = (app_image_t*) malloc(sizeof(*app_image)); + if(app_image != NULL){ + + app_image->num_allocated_pages = MAX_PAGE_NUMBER; + app_image->num_pages = 0; + app_image->num_received_pages = 0; + app_image->page_size = MAX_PAGE_SIZE; + //app_image->nonce = {0}; + //app_image->auth = {0}; + //app_image->pages = {0}; + + }else { + SERIALOUT("Memory allocation fail for ram image \r\n"); + status = BL_RAM_ALLOC_FAIL; + } + + } + + SERIALOUT("\r\n%s err=%d\r\n", "image_on_ram", COMM_SUCCESS); + +} + +int SH_BOOTLDR_get_pagesz(const char *null_arg){ + + int status; + int pageSize; + + if (bootldrState.flag_image_on_ram) { + SERIALOUT("\r\n%s value=%d err=%d\r\n", "page_size", MAX_PAGE_SIZE, COMM_SUCCESS); + app_image->page_size = MAX_PAGE_SIZE; + bootldrState.page_size = MAX_PAGE_SIZE; + SERIALOUT("\r\n%s err=%d\r\n", "image_on_ram", 1); + + }else { + + status = sh_get_bootloader_pagesz(&pageSize); + if (status == 0x00 ){ + if( pageSize == -2){ + SERIALOUT("\r\n Page size over maximum allowable \r\n"); + status = -1; + }else { + SERIALOUT("\r\n%s value=%d err=%d\r\n", "page_size", pageSize, status); + bootldrState.page_size = pageSize; + } + }else + SERIALOUT("\r\n%s err=%d\r\n", "page_size", status); + + } + return status; + +} + +int SH_BOOTLDR_set_pagecount(const char *arg){ + + int status = -1; + int pageCount; + + if(sscanf(arg, "%*s %d", &pageCount)){ + + if(bootldrState.flag_image_on_ram){ + app_image->num_pages = (pageCount <= MAX_PAGE_NUMBER)? pageCount:0; + app_image->num_allocated_pages = MAX_PAGE_NUMBER; + bootldrState.num_pages = app_image->num_pages; + + }else { + + status = sh_set_bootloader_numberofpages(pageCount); + if (status == 0x00){ + bootldrState.num_pages = pageCount; + }else + bootldrState.num_pages = 0; + } + } + SERIALOUT("\r\n%s err=%d\r\n", "num_pages", status); + return status; + +} + +int SH_BOOTLDR_set_iv(const char *arg) { + + uint8_t iv_bytes[AES_NONCE_SIZE]; + int status = parse_iv(arg, &iv_bytes[0]); + if( status == 0x00){ + + if(bootldrState.flag_image_on_ram){ + int i=0; + for(i = 0 ; i != AES_NONCE_SIZE ; i++) + app_image->nonce[i] = iv_bytes[i]; + bootldrState.is_iv_set = 1; + + }else { + + status = sh_set_bootloader_iv(iv_bytes); + if( status == 0x00 ) { + bootldrState.is_iv_set = 1; + } + else { + bootldrState.is_iv_set = 0; + status = COMM_GENERAL_ERROR; + } + } + } + SERIALOUT("\r\n%s err=%d\r\n", "set_iv", status); + + return status; + +} + + +int SH_BOOTLDR_set_authentication(const char *arg){ + + uint8_t auth_bytes[AES_AUTH_SIZE]; + int status = parse_auth(arg, &auth_bytes[0]); + if( status == 0x00){ + + if(bootldrState.flag_image_on_ram){ + int i=0; + for(i = 0 ; i != AES_AUTH_SIZE ; i++) + app_image->auth[i] = auth_bytes[i]; + bootldrState.is_auth_done = 1; + + }else { + + status = sh_set_bootloader_auth(auth_bytes); + if( status == 0x00 ){ + bootldrState.is_auth_done = 1; + } + else + status = COMM_GENERAL_ERROR; + } + + } + SERIALOUT("\r\n%s err=%d\r\n", "set_auth", status); + + return status; + +} + +int SH_BOOTLDR_eraseflash(const char *null_arg){ + + int status; + if(bootldrState.flag_image_on_ram){ + SERIALOUT("\r\n%s err=%d\r\n", "erase", COMM_SUCCESS); + status == 0x00 /*SS_SUCCESS*/; + + }else { + + status = sh_set_bootloader_erase(); + if(status == 0x00 /*SS_SUCCESS*/) { + bootldrState.is_flash_erased = 1; + }else{ + status = COMM_GENERAL_ERROR; + } + SERIALOUT("\r\n%s err=%d\r\n", "erase", status); + + } + return status; + +} + + +int SH_BOOTLDR_receive_image_to_ram(void){ + + + int status; + int totalBytes = 0; + int currentPage = 1; + + if( app_image != NULL && app_image->num_allocated_pages > 0) { + + uint8_t *page = &app_image->pages[0]; + uint32_t offset = 0; + while (currentPage <= app_image->num_pages) { + + while (totalBytes < (MAX_PAGE_SIZE + CHECKBYTES_SIZE)) { + page[totalBytes++] = SERIALIN(); // daplink.getc(); ; /////////////////////////////////////////////////////m_USB->_getc(); + } + + currentPage++; + SERIALOUT("\r\npageFlashDone err=%d\r\n", COMM_SUCCESS); + + offset += MAX_PAGE_SIZE + CHECKBYTES_SIZE; + page = &app_image->pages[offset]; + totalBytes = 0; + } + + app_image->num_received_pages = currentPage; + + status = COMM_SUCCESS; + + }else + status = COMM_GENERAL_ERROR; + + return status; + +} + +int SH_BOOTLDR_flash_pages(void){ + + + int totalBytes = 0; + int currentPage = 1; + char charbuf_flash[256]; + int data_len_flash = 0; + int status; + + static uint8_t tx_buf[ BOOTLOADER_MAX_PAGE_SIZE + CHECKBYTES_SIZE + FLASHCMDBYTES] = { SS_FAM_W_BOOTLOADER, SS_CMDIDX_SENDPAGE }; + uint8_t *data_buffer = &tx_buf[2]; + + if(!is_hub_ready_for_flash()){ + printf("missing condition for flashing: no page size , no page number, iv notset , no outhentication , flash noterased or mode is not bootloader!\r\n"); + clear_state_info(); + return -1; + } + printf(" \r\n NOW WE ARE FLASHING THE PAGES..........\r\n"); + printf(" \r\n page_size: %d \r\n", bootldrState.page_size); + printf(" \r\n num_pages: %d \r\n", bootldrState.num_pages); + + while (currentPage <= bootldrState.num_pages) { + + while (totalBytes < (bootldrState.page_size + CHECKBYTES_SIZE)) { + data_buffer[totalBytes++] = SERIALIN(); //daplink.getc(); //m_USB->_getc(); !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! MYG + //Here we should be able to take the data over BLE + } + printf(" \r\n NOW WE GOT A PAGE..........\r\n"); + //status = sh_bootloader_flashpage(&tx_buf[0] , bootldrState.page_size); + + status = sh_write_cmd(tx_buf, bootldrState.page_size + CHECKBYTES_SIZE + 2, 2000); + + if (status == 0x00) + printf(" \r\n NOW WE PUSHED A PAGE..........\r\n"); +/* + if (status == 0x00){ + currentPage++; + SERIALOUT("\r\npageFlashDone err=%d\r\n", COMM_SUCCESS); + }else{ + + if (status == SS_ERR_BTLDR_CHECKSUM) + SERIALOUT("\r\npageFlashDone err=%d\r\n", BL_FLASH_ERR_CHECKSUM); + else + SERIALOUT("\r\npageFlashDone err=%d\r\n", BL_FLASH_ERR_GENERAL); + + } + */ + + if (status == SS_ERR_BTLDR_CHECKSUM) { + + data_len_flash = snprintf(charbuf_flash, sizeof(charbuf_flash), "\r\npageFlashDone err=%d\r\n", FLASH_ERR_CHECKSUM); + SERIALOUT(charbuf_flash); + } else if (status != SS_SUCCESS) { + + data_len_flash = snprintf(charbuf_flash, sizeof(charbuf_flash), "\r\npageFlashDone err=%d\r\n", FLASH_ERR_GENERAL); + SERIALOUT(charbuf_flash); + } else { + currentPage++; + + data_len_flash = snprintf(charbuf_flash, sizeof(charbuf_flash), "\r\npageFlashDone err=%d\r\n", COMM_SUCCESS); + SERIALOUT(charbuf_flash); + } + totalBytes = 0; + + } + //SERIALOUT(" all pages are flashed \r\n"); + clear_state_info(); + + return status; + +} + + +int SH_BOOTLDR_flash(const char *null_arg){ + + int status; + if(bootldrState.flag_image_on_ram) + status = SH_BOOTLDR_receive_image_to_ram(); + else + status = SH_BOOTLDR_flash_pages(); + + SERIALOUT("\r\n%s err=%d\r\n", "flash", status); + + return status; +} + + +int SH_BOOTLDR_flash_appimage_from_ram(const char *null_arg){ + + + int currentPage = 1; + uint32_t offset = 0; + int ret; + + if(app_image == NULL) + return -1; + + /* Put device to bootloader mode */ + int status = SH_BOOTLDR_enter_blmode(NULL); + if( status != 0x00) + return -1; + + wait_ms(10); + + status = sh_set_bootloader_numberofpages(app_image->num_pages); + SERIALOUT("*** set_num_page... ret: %d\n", ret); + if (status != 0x00) { + return BL_SET_NUM_PAGES_FAIL; + } + + status = sh_set_bootloader_iv(app_image->nonce); + SERIALOUT("*** set_iv... ret: %d\n", ret); + if (status != 0) { + return BL_SET_IV_FAIL; + } + + status = sh_set_bootloader_auth(app_image->auth); + SERIALOUT("*** set_auth... ret: %d\n", ret); + if (status != 0) { + return BL_FLASH_ERR_AUTH; + } + + status = sh_set_bootloader_erase() ; + SERIALOUT("*** erase app memory... ret: %d\n", ret); + if (status != 0) { + return BL_FLASS_ERASE_FAIL; + } + + static uint8_t tx_buf[MAX_PAGE_SIZE + CHECKBYTES_SIZE + 2]; + + tx_buf[0] = SS_FAM_W_BOOTLOADER; + tx_buf[1] = SS_CMDIDX_SENDPAGE; + + while (currentPage <= app_image->num_pages) { + + memcpy(&tx_buf[2], &app_image->pages[offset], MAX_PAGE_SIZE + CHECKBYTES_SIZE); + + status = sh_write_cmd(tx_buf, MAX_PAGE_SIZE + CHECKBYTES_SIZE + 2, bootldrState.bootcmds_delay_factor * PAGE_WRITE_DELAY_MS); + + if (status == SS_ERR_BTLDR_CHECKSUM) { + + SERIALOUT("\r\npageFlashDone err=%d\r\n", BL_FLASH_ERR_CHECKSUM); + break; + } else if (status != SS_SUCCESS) { + + SERIALOUT("\r\npageFlashDone err=%d\r\n", BL_FLASH_ERR_GENERAL); + break; + } else { + + SERIALOUT("\r\npageFlashDone err=%d\r\n", COMM_SUCCESS); + } + + offset += MAX_PAGE_SIZE + CHECKBYTES_SIZE; + currentPage++; + } + + return COMM_SUCCESS; + +} + +int SH_BOOTLDR_set_host_ebl_mode(const char *arg) { + + int status; + int tmp; + sscanf(arg, "%*s %*s %*s %d", &tmp); + status = sh_set_ebl_mode(tmp); + if( status == 0x00) { + bootldrState.ebl_mode = tmp; + }else + status = COMM_INVALID_PARAM; + + SERIALOUT("\r\n%s err=%d\r\n", "set_cfg host ebl",status); + + return status; + +} + +int SH_BOOTLDR_get_host_ebl_mode(const char *null_arg){ + + int value; + value = sh_get_ebl_mode(); + SERIALOUT("\r\n%s value=%s\r\n", "get_cfg host ebl", (value==1)? "GPIO_RST_MODE":"CMD_RST_MODE"); + return 0x00; +} + +int SH_BOOTLDR_set_host_bootcmds_delay_factor( const char *arg) { + + int status; + int tmp; + sscanf(arg, "%*s %*s %*s %d", &tmp); + status = sh_set_bootloader_delayfactor( tmp); + if( status == 0x00) { + bootldrState.bootcmds_delay_factor = tmp; + }else + status = COMM_INVALID_PARAM; + + SERIALOUT("\r\n%s err=%d\r\n", "set_cfg host cdf",status); + + return status; + +} + +int SH_BOOTLDR_get_host_bootcmds_delay_factor( const char *null_arg){ + + int value; + value = sh_get_bootloader_delayfactor(); + SERIALOUT("\r\n%s value=%d \r\n", "get_cfg host cdf", value); + return 0x00; + +} + +static int is_hub_ready_for_flash(void){ + + int status = 0; + if( bootldrState.hub_mode_bootloader == 1 && + bootldrState.is_auth_done == 1 && + bootldrState.is_iv_set == 1 && + bootldrState.is_flash_erased == 1 && + bootldrState.num_pages > 0 && + bootldrState.page_size > 0 ) + status = 1; + + return status; +} + +static void clear_state_info(void) { + + bootldrState.is_auth_done = 0; + bootldrState.is_iv_set = 0; + bootldrState.is_flash_erased = 0; + bootldrState.num_pages = 0; + bootldrState.page_size = 0; + bootldrState.hub_mode_bootloader; + + return; +} + +static int parse_iv(const char* cmd, uint8_t* iv_bytes) { + + int status = 0x00; + char cmdStr[] = "set_iv "; + int length = strlen(cmd); + int expected_length = strlen(cmdStr) + 2*AES_NONCE_SIZE; + + if (length != expected_length) { + SERIALOUT("Couldn't parse IV, incorrect number of characters (len:%d, expected:%d)\n", + length, expected_length); + status = COMM_INVALID_PARAM; + }else{ + + const char* ivPtr = cmd + strlen(cmdStr); + int num_found; + int byteVal; + for (int ividx = 0; ividx < AES_NONCE_SIZE; ividx++) { + num_found = sscanf(ivPtr, "%2X", &byteVal); + + if (num_found != 1 || byteVal > 0xFF) { + status = COMM_INVALID_PARAM; + //break; // + return status; + } + iv_bytes[ividx] = (uint8_t)byteVal; + ivPtr += 2; + } + } + return status; + +} + + +static int parse_auth(const char* cmd, uint8_t *auth_bytes){ + + int status = 0x00; + char cmdStr[] = "set_auth "; + int length = strlen(cmd); + int expected_length = strlen(cmdStr) + 2*AES_AUTH_SIZE; + + if (length != expected_length) { + status = -1; + }else{ + + const char* macPtr = cmd + strlen(cmdStr); + + int num_found; + int byteVal; + for (int aidx = 0; aidx < AES_AUTH_SIZE; aidx++) { + num_found = sscanf(macPtr, "%2X", &byteVal); + + if (num_found != 1 || byteVal > 0xFF) { + status = COMM_INVALID_PARAM;; + //break; // + return status; + } + + auth_bytes[aidx] = (uint8_t)byteVal; + macPtr += 2; + } + + } + return status; + +} + +