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