346 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			346 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/****************************************************************************
 | 
						|
 | 
						|
Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics. ALL RIGHTS RESERVED.
 | 
						|
 | 
						|
This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics and MAY NOT
 | 
						|
be copied by any method or incorporated into another program without
 | 
						|
the express written consent of Aerospace C.Power. This Information or any portion
 | 
						|
thereof remains the property of Aerospace C.Power. The Information contained herein
 | 
						|
is believed to be accurate and Aerospace C.Power assumes no responsibility or
 | 
						|
liability for its use in any way and conveys no license or title under
 | 
						|
any patent or copyright and makes no representation or warranty that this
 | 
						|
Information is free from patent or copyright infringement.
 | 
						|
 | 
						|
****************************************************************************/
 | 
						|
/* os_shim header files */
 | 
						|
#include "os_types_api.h"
 | 
						|
#include "os_utils_api.h"
 | 
						|
 | 
						|
/* iot common header files */
 | 
						|
#include "iot_io_api.h"
 | 
						|
#include "iot_module_api.h"
 | 
						|
#include "iot_errno_api.h"
 | 
						|
#include "iot_board_api.h"
 | 
						|
#include "iot_oem_api.h"
 | 
						|
#include "iot_utils_api.h"
 | 
						|
#include "iot_system_api.h"
 | 
						|
#include "iot_bitmap_api.h"
 | 
						|
#include "iot_upgrade_api.h"
 | 
						|
 | 
						|
#include "iot_bsrm_common.h"
 | 
						|
#include "iot_bsrm_upgrade.h"
 | 
						|
 | 
						|
#if IOT_BSRM_MODE
 | 
						|
 | 
						|
/* bsrm upgrade windows time, unit:  1s */
 | 
						|
#define IOT_BSRM_UPGRADE_WINDOWS_TIME                 (8 * 60 * 60)
 | 
						|
 | 
						|
static iot_bsrm_upgrade_t *bsrm_upgrade = NULL;
 | 
						|
 | 
						|
static void iot_bsrm_upgrade_goto_state(uint8_t new_state)
 | 
						|
{
 | 
						|
    iot_bsrm_printf("bsrm_upgrade: state from %d to %d.\n", bsrm_upgrade->state,
 | 
						|
        new_state);
 | 
						|
    if (bsrm_upgrade->state != new_state) {
 | 
						|
        bsrm_upgrade->state = new_state;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
uint32_t iot_bsrm_upgrade_init()
 | 
						|
{
 | 
						|
    uint32_t ret = ERR_OK;
 | 
						|
 | 
						|
    if (bsrm_upgrade) {
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    bsrm_upgrade = os_mem_malloc(IOT_BSRM_MID, sizeof(*bsrm_upgrade));
 | 
						|
    if (bsrm_upgrade == NULL) {
 | 
						|
        ret = ERR_FAIL;
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    bsrm_upgrade->state = IOT_BSRM_UPGRADE_ST_INVALID;
 | 
						|
    bsrm_upgrade->upgrade_id = 0;
 | 
						|
 | 
						|
    if (iot_upgrade_get_part(&bsrm_upgrade->current_part)) {
 | 
						|
        ret = ERR_FAIL;
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
 | 
						|
    bsrm_upgrade->crc = iot_upgrade_get_fw_crc(bsrm_upgrade->current_part);
 | 
						|
    if (bsrm_upgrade->crc == 0) {
 | 
						|
        bsrm_upgrade->crc = iot_upgrade_get_backup_crc();
 | 
						|
        iot_upgrade_save_fw_crc(bsrm_upgrade->current_part, bsrm_upgrade->crc);
 | 
						|
    }
 | 
						|
out:
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
void iot_bsrm_upgrade_deinit()
 | 
						|
{
 | 
						|
    if (bsrm_upgrade) {
 | 
						|
        os_mem_free(bsrm_upgrade);
 | 
						|
        bsrm_upgrade = NULL;
 | 
						|
    }
 | 
						|
    iot_bsrm_printf("%s successful\n", __FUNCTION__);
 | 
						|
}
 | 
						|
 | 
						|
static void iot_bsrm_upgrade_init_info()
 | 
						|
{
 | 
						|
    iot_bsrm_upgrade_goto_state(IOT_BSRM_UPGRADE_ST_IDLE);
 | 
						|
    bsrm_upgrade->block_size = 0;
 | 
						|
    bsrm_upgrade->total_block_cnt = 0;
 | 
						|
    bsrm_upgrade->received_size = 0;
 | 
						|
    bsrm_upgrade->rec_block_cnt = 0;
 | 
						|
    bsrm_upgrade->window_tm = IOT_BSRM_UPGRADE_WINDOWS_TIME;
 | 
						|
    bsrm_upgrade->skip = 0;
 | 
						|
    os_mem_set(bsrm_upgrade->block_bitmap, 0, IOT_BSRM_BM_SIZE);
 | 
						|
}
 | 
						|
 | 
						|
uint32_t iot_bsrm_upgrade_stop()
 | 
						|
{
 | 
						|
    uint32_t part;
 | 
						|
 | 
						|
    if (bsrm_upgrade->state <= IOT_BSRM_UPGRADE_ST_IDLE) {
 | 
						|
        return ERR_OK;
 | 
						|
    }
 | 
						|
 | 
						|
    iot_pkg_upgrade_cancel_commit(0, 1);
 | 
						|
    if (ERR_OK == iot_upgrade_get_part(&part)) {
 | 
						|
        bsrm_upgrade->crc = iot_upgrade_get_fw_crc(part);
 | 
						|
        if (bsrm_upgrade->crc == 0) {
 | 
						|
            bsrm_upgrade->crc = iot_upgrade_get_backup_crc();
 | 
						|
            iot_upgrade_save_fw_crc(part, bsrm_upgrade->crc);
 | 
						|
        }
 | 
						|
    }
 | 
						|
    iot_bsrm_upgrade_init_info();
 | 
						|
    return ERR_OK;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t iot_bsrm_upgrade_start(uint32_t total_block_cnt, uint32_t block_size)
 | 
						|
{
 | 
						|
    if (bsrm_upgrade->state > IOT_BSRM_UPGRADE_ST_IDLE) {
 | 
						|
        return ERR_FAIL;
 | 
						|
    }
 | 
						|
 | 
						|
    if (total_block_cnt > IOT_BSRM_BM_SIZE * 8) {
 | 
						|
        iot_bsrm_printf("bsrm_upgrade: exceed max block count\n");
 | 
						|
        return ERR_FAIL;
 | 
						|
    }
 | 
						|
 | 
						|
    bsrm_upgrade->upgrade_id++;
 | 
						|
    if (bsrm_upgrade->upgrade_id == 0) {
 | 
						|
        bsrm_upgrade->upgrade_id = 1;
 | 
						|
    }
 | 
						|
 | 
						|
    iot_bsrm_upgrade_init_info();
 | 
						|
    bsrm_upgrade->block_size = block_size;
 | 
						|
    bsrm_upgrade->total_block_cnt = total_block_cnt;
 | 
						|
    return ERR_OK;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t iot_bsrm_upgrade_data(uint32_t block_index, uint32_t block_len,
 | 
						|
    uint8_t *data)
 | 
						|
{
 | 
						|
    iot_pkt_t *trans_pkt;
 | 
						|
    iot_trans_cmd_t trans_cmd = {0};
 | 
						|
    uint32_t ret;
 | 
						|
    /* start upgrade when receive the 1st package,  */
 | 
						|
    iot_start_rst_t rst;
 | 
						|
    uint32_t file_size;
 | 
						|
    uint32_t file_crc;
 | 
						|
 | 
						|
    if (bsrm_upgrade->skip ||
 | 
						|
        (bsrm_upgrade->state > IOT_BSRM_UPGRADE_ST_RECEIVE)) {
 | 
						|
        ret = ERR_OK;
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
 | 
						|
    if (block_index == 0) {
 | 
						|
        /* check data */
 | 
						|
        if (IOT_FILE_TYPE_INVALID == iot_get_file_type(data)) {
 | 
						|
            /* reject invalid data packet. */
 | 
						|
            iot_bsrm_printf("%s invalid upgrade file\n", __FUNCTION__);
 | 
						|
            ret = ERR_FAIL;
 | 
						|
            goto out;
 | 
						|
        }
 | 
						|
 | 
						|
        /* check vendor id */
 | 
						|
        if (iot_get_vendor_id(data) != iot_board_load_user_vendor_id()) {
 | 
						|
            /* reject invalid data packet. */
 | 
						|
            iot_bsrm_printf("%s invalid vendor id\n", __FUNCTION__);
 | 
						|
            ret = ERR_FAIL;
 | 
						|
            goto out;
 | 
						|
        }
 | 
						|
 | 
						|
        file_crc = iot_get_file_crc(data);
 | 
						|
        if (bsrm_upgrade->crc == file_crc) {
 | 
						|
            iot_bsrm_printf("%s crc matching, skip upgrade\n", __FUNCTION__);
 | 
						|
            bsrm_upgrade->skip = 1;
 | 
						|
            ret = ERR_OK;
 | 
						|
            goto out;
 | 
						|
        }
 | 
						|
        bsrm_upgrade->crc = file_crc;
 | 
						|
        file_size = iot_get_file_len(data);
 | 
						|
        ret = iot_pkg_upgrade_start(&rst, bsrm_upgrade->upgrade_id,
 | 
						|
            bsrm_upgrade->block_size, file_size, 0, 0, 0, data);
 | 
						|
        if (ret != ERR_OK) {
 | 
						|
            iot_bsrm_printf("upgrade: start failed. result = %d\n",
 | 
						|
                ret);
 | 
						|
            goto out;
 | 
						|
        } else {
 | 
						|
            iot_bsrm_printf("upgrade: start OK, crc: %lu, file size: %lu.\n",
 | 
						|
                bsrm_upgrade->crc, file_size);
 | 
						|
        }
 | 
						|
        iot_bsrm_upgrade_goto_state(IOT_BSRM_UPGRADE_ST_RECEIVE);
 | 
						|
    }
 | 
						|
 | 
						|
    if (bsrm_upgrade->state != IOT_BSRM_UPGRADE_ST_RECEIVE) {
 | 
						|
        ret = ERR_FAIL;
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
 | 
						|
    if (iot_bitmap_is_set(bsrm_upgrade->block_bitmap, IOT_BSRM_BM_SIZE,
 | 
						|
        block_index + 1)) {
 | 
						|
        /* block was processed before */
 | 
						|
        return ERR_OK;
 | 
						|
    }
 | 
						|
 | 
						|
    trans_pkt = (iot_pkt_t*)iot_pkt_alloc(block_len, IOT_BSRM_MID);
 | 
						|
    os_mem_cpy(iot_pkt_put(trans_pkt, block_len), data, block_len);
 | 
						|
 | 
						|
    trans_cmd.block_num = block_index;
 | 
						|
    trans_cmd.id = bsrm_upgrade->upgrade_id;
 | 
						|
    trans_cmd.crc_flag = 0;
 | 
						|
    trans_cmd.data = trans_pkt;
 | 
						|
    trans_cmd.data_type = UPGRADE_DATA_TYPE_PKG;
 | 
						|
    ret = iot_pkg_upgrade_trans(&trans_cmd);
 | 
						|
    if (ret != ERR_OK) {
 | 
						|
        ret = ERR_FAIL;
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
 | 
						|
    if (block_index * bsrm_upgrade->block_size + block_len >
 | 
						|
        IOT_BSRM_MAX_SIZE) {
 | 
						|
        iot_bsrm_printf("upgrade: data exceed max size.\n");
 | 
						|
        ret = ERR_FAIL;
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
 | 
						|
    /* record block bitmap */
 | 
						|
    iot_bitmap_set(bsrm_upgrade->block_bitmap,
 | 
						|
        (uint16_t)IOT_BSRM_BM_SIZE, block_index + 1);
 | 
						|
    bsrm_upgrade->rec_block_cnt++;
 | 
						|
    bsrm_upgrade->received_size += block_len;
 | 
						|
    iot_bsrm_printf("upgrade: rec cnt: %d, total: %d, bitmap size: %d\n",
 | 
						|
        bsrm_upgrade->rec_block_cnt, bsrm_upgrade->total_block_cnt,
 | 
						|
        iot_bitmap_cbs(bsrm_upgrade->block_bitmap, (uint16_t)IOT_BSRM_BM_SIZE));
 | 
						|
    if (bsrm_upgrade->rec_block_cnt >= bsrm_upgrade->total_block_cnt &&
 | 
						|
        iot_bitmap_cbs(bsrm_upgrade->block_bitmap, (uint16_t)IOT_BSRM_BM_SIZE)
 | 
						|
        >= bsrm_upgrade->total_block_cnt) {
 | 
						|
        iot_bsrm_upgrade_goto_state(IOT_BSRM_UPGRADE_ST_RECV_DONE);
 | 
						|
        iot_bsrm_upgrade_exe();
 | 
						|
    }
 | 
						|
    ret = ERR_OK;
 | 
						|
out:
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
static void iot_bsrm_upgrade_save_to_flash()
 | 
						|
{
 | 
						|
    uint32_t other_part;
 | 
						|
    other_part = iot_upgrade_get_another_part(bsrm_upgrade->current_part);
 | 
						|
    iot_bsrm_printf("bsrm_upgrade: cur_part = %d, save data to part = %d\n",
 | 
						|
        bsrm_upgrade->current_part, other_part);
 | 
						|
    iot_upgrade_save_fw_crc(other_part, bsrm_upgrade->crc);
 | 
						|
    iot_upgrade_save_fw_blksize(other_part, bsrm_upgrade->block_size);
 | 
						|
}
 | 
						|
 | 
						|
uint32_t iot_bsrm_upgrade_exe()
 | 
						|
{
 | 
						|
    if (bsrm_upgrade->state != IOT_BSRM_UPGRADE_ST_RECV_DONE) {
 | 
						|
        return ERR_FAIL;
 | 
						|
    }
 | 
						|
    /* save crc upgrade info */
 | 
						|
    iot_bsrm_upgrade_save_to_flash();
 | 
						|
    /* commit */
 | 
						|
    iot_pkg_upgrade_commit(bsrm_upgrade->upgrade_id);
 | 
						|
    /* reset */
 | 
						|
    iot_upgrade_reset();
 | 
						|
    return ERR_OK;
 | 
						|
}
 | 
						|
 | 
						|
void iot_bsrm_upgrade_windows()
 | 
						|
{
 | 
						|
    if (bsrm_upgrade->state <= IOT_BSRM_UPGRADE_ST_IDLE) {
 | 
						|
        return;
 | 
						|
    }
 | 
						|
    if (!bsrm_upgrade->window_tm) {
 | 
						|
        if (bsrm_upgrade->state == IOT_BSRM_UPGRADE_ST_RECV_DONE) {
 | 
						|
            iot_bsrm_upgrade_exe();
 | 
						|
        } else {
 | 
						|
            iot_bsrm_upgrade_stop();
 | 
						|
        }
 | 
						|
    } else {
 | 
						|
        bsrm_upgrade->window_tm--;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
uint32_t iot_bsrm_query_upgrade_info(iot_bsrm_upgrade_info_t
 | 
						|
    *query_info)
 | 
						|
{
 | 
						|
    if (!query_info) {
 | 
						|
        return ERR_INVAL;
 | 
						|
    }
 | 
						|
 | 
						|
    query_info->block_cnt = bsrm_upgrade->total_block_cnt;
 | 
						|
    query_info->crc = bsrm_upgrade->crc;
 | 
						|
    query_info->recv_cnt = bsrm_upgrade->rec_block_cnt;
 | 
						|
 | 
						|
    if (IOT_BSRM_UPGRADE_ST_IDLE >= bsrm_upgrade->state) {
 | 
						|
        if (bsrm_upgrade->skip) {
 | 
						|
            query_info->state = IOT_BSRM_UPGRADE_ST_RECV_DONE;
 | 
						|
        } else {
 | 
						|
            query_info->state = IOT_BSRM_UPGRADE_ST_IDLE;
 | 
						|
        }
 | 
						|
    } else {
 | 
						|
        query_info->state = IOT_BSRM_UPGRADE_ST_RECEIVE;
 | 
						|
    }
 | 
						|
    return ERR_OK;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t iot_bsrm_upgrade_query_bitmap_info(uint8_t *bitmap,
 | 
						|
    uint32_t start_index, uint32_t size)
 | 
						|
{
 | 
						|
    uint32_t file_bitmap_size;
 | 
						|
    uint32_t invalid_size;
 | 
						|
 | 
						|
    if ((!bitmap) || (!size)) {
 | 
						|
        return 0;
 | 
						|
    }
 | 
						|
 | 
						|
    /* bsrm not recv upgrade file, upgrade file block bitmap is zero */
 | 
						|
    if (IOT_BSRM_UPGRADE_ST_IDLE >= bsrm_upgrade->state) {
 | 
						|
        file_bitmap_size = 0;
 | 
						|
    } else {
 | 
						|
        /* upgrade file bolck bitmap size */
 | 
						|
        file_bitmap_size = (bsrm_upgrade->total_block_cnt + 7) >> 3;
 | 
						|
    }
 | 
						|
 | 
						|
    if (start_index >= file_bitmap_size) {
 | 
						|
        return 0;
 | 
						|
    }
 | 
						|
 | 
						|
    if ((start_index + size) > file_bitmap_size) {
 | 
						|
        /* invalid bitmap size */
 | 
						|
        invalid_size = start_index + size - file_bitmap_size;
 | 
						|
        /* valid bitmap size */
 | 
						|
        size = file_bitmap_size - start_index;
 | 
						|
        /* set default invalid bitmap value */
 | 
						|
        os_mem_set(bitmap + size, 0, invalid_size);
 | 
						|
    }
 | 
						|
    os_mem_cpy(bitmap, bsrm_upgrade->block_bitmap + start_index, size);
 | 
						|
    return size;
 | 
						|
}
 | 
						|
 | 
						|
#endif /* IOT_BSRM_MODE */
 |