test

Dependencies:   BMI160 max32630hsp3 MemoryLCD USBDevice

bootloader/bootldrAPI.cpp

Committer:
seyhmuscacina
Date:
2019-03-25
Revision:
3:b8989dab0f88
Parent:
0:ac4dea3e2894

File content as of revision 3:b8989dab0f88:

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

}