Files
kunlun/app/bsrm/iot_bsrm_upgrade.c
2024-09-28 14:24:04 +08:00

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