1244 lines
43 KiB
C
1244 lines
43 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_event_api.h"
|
|
#include "os_timer_api.h"
|
|
|
|
/* iot common header files */
|
|
#include "iot_io_api.h"
|
|
#include "iot_plc_cco_api.h"
|
|
#include "iot_module_api.h"
|
|
#include "iot_errno_api.h"
|
|
#include "iot_dbglog_api.h"
|
|
#include "iot_task_api.h"
|
|
#include "iot_plc_msg_api.h"
|
|
#include "iot_crc_api.h"
|
|
#include "iot_version_api.h"
|
|
#include "iot_oem_api.h"
|
|
#include "iot_board_api.h"
|
|
|
|
/* smart grid internal header files */
|
|
#include "iot_sg_fr.h"
|
|
#include "proto_gw_app.h"
|
|
#include "iot_sg.h"
|
|
#include "iot_sg_msg.h"
|
|
#include "iot_sg_sta_gw.h"
|
|
#include "iot_sg_sta_nw.h"
|
|
#include "iot_sg_sta_upgrade.h"
|
|
#include "iot_upgrade_api.h"
|
|
#include "iot_sg_sta_ext_upgrade.h"
|
|
|
|
#include "os_utils_api.h"
|
|
#include "iot_plc_led_api.h"
|
|
|
|
/* default trail-run timeout value in second */
|
|
#define IOT_SG_STA_DEFAULT_TRAIL_RUN_DUR (0)
|
|
|
|
#if (IOT_SMART_GRID_ENABLE)
|
|
|
|
/* upgrade timer time out function */
|
|
void iot_sg_sta_upgrade_func(timer_id_t timer_id, void *arg)
|
|
{
|
|
(void)timer_id;
|
|
(void)arg;
|
|
iot_sg_msg_t *msg;
|
|
|
|
msg = (iot_sg_msg_t *)iot_task_alloc_msg(p_sg_glb->task_h);
|
|
if (msg) {
|
|
msg->task_msg.type = IOT_SG_MSG_TYPE_TIMER;
|
|
msg->task_msg.id = IOT_SG_MSG_ID_TIMER_UPGRADE;
|
|
iot_task_queue_msg(p_sg_glb->task_h, &msg->task_msg,
|
|
IOT_SG_MSG_QUEUE_LP);
|
|
} else {
|
|
IOT_ASSERT(0);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief: get a up aligned value
|
|
* @param value: the value to get its aligned value
|
|
* @param align_base: align base
|
|
* @return: the up aligned value.
|
|
*/
|
|
static uint32_t iot_sg_sta_get_align(uint32_t value, uint32_t align_base) {
|
|
uint32_t rest;
|
|
uint32_t pad_byte = 0;
|
|
if (align_base == 0) {
|
|
return value;
|
|
}
|
|
|
|
rest = value % align_base;
|
|
if (rest) {
|
|
pad_byte = align_base - rest;
|
|
}
|
|
|
|
return value + pad_byte;
|
|
}
|
|
|
|
static void iot_sg_sta_renew_exit_reason_code(uint8_t exit_reason)
|
|
{
|
|
iot_upgrade_save_upgrade_status(exit_reason);
|
|
p_sg_glb->desc.sta->upgrade_info.exit_reason = exit_reason;
|
|
}
|
|
|
|
static void iot_sg_sta_start_upgrade_timer(uint32_t duration)
|
|
{
|
|
iot_sg_sta_upgrade_info_t *upgrade_info = &p_sg_glb->desc.sta->upgrade_info;
|
|
|
|
iot_task_clean_msg(p_sg_glb->task_h, IOT_SG_MSG_TYPE_TIMER,
|
|
IOT_SG_MSG_ID_TIMER_UPGRADE);
|
|
os_start_timer(upgrade_info->upgrade_timer, duration);
|
|
}
|
|
|
|
static void iot_sg_sta_stop_upgrade_timer()
|
|
{
|
|
iot_sg_sta_upgrade_info_t *upgrade_info = &p_sg_glb->desc.sta->upgrade_info;
|
|
|
|
os_stop_timer(upgrade_info->upgrade_timer);
|
|
iot_task_clean_msg(p_sg_glb->task_h, IOT_SG_MSG_TYPE_TIMER,
|
|
IOT_SG_MSG_ID_TIMER_UPGRADE);
|
|
}
|
|
|
|
void iot_sg_sta_send_start_ack(uint32_t id, uint8_t msg_type,
|
|
uint32_t result)
|
|
{
|
|
iot_sg_sta_upgrade_info_t *upgrade_info = &p_sg_glb->desc.sta->upgrade_info;
|
|
|
|
if (upgrade_info->session_type == IOT_SG_STA_UPGRADE_SESSION_TYPE_GW) {
|
|
iot_sg_sta_gw_send_start_ack(id, msg_type, result);
|
|
} else if (upgrade_info->session_type ==
|
|
IOT_SG_STA_UPGRADE_SESSION_TYPE_NW) {
|
|
iot_sg_sta_nw_send_start_ack(id, msg_type, result);
|
|
}
|
|
}
|
|
|
|
void iot_sg_sta_send_query_reply(uint32_t id, uint32_t start_seq,
|
|
uint16_t status, uint16_t cnt, iot_pkt_t *bitmap_pkt, uint8_t msg_type,
|
|
uint8_t session_type)
|
|
{
|
|
if (session_type == IOT_SG_STA_UPGRADE_SESSION_TYPE_GW) {
|
|
iot_sg_sta_gw_send_query_reply(id, start_seq, status, cnt,
|
|
bitmap_pkt, msg_type);
|
|
} else if (session_type == IOT_SG_STA_UPGRADE_SESSION_TYPE_NW) {
|
|
(void)cnt;
|
|
iot_sg_sta_nw_send_query_reply(id, start_seq, status, bitmap_pkt,
|
|
msg_type);
|
|
} else {
|
|
iot_pkt_free(bitmap_pkt);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief: calc CRC of the upgrading file. It can only be called when upgrading.
|
|
* @retval: the crc of upgrading file.
|
|
*/
|
|
uint32_t iot_sg_sta_get_crc()
|
|
{
|
|
uint32_t file_len = 0;
|
|
uint32_t file_block_len = 0;
|
|
uint32_t crc = 0xFFFFFFFF;
|
|
uint32_t offset = 0;
|
|
uint32_t len = 0;
|
|
uint32_t align_size = 2400;
|
|
uint8_t* ptr = NULL;
|
|
uint32_t pib_size;
|
|
uint32_t fw_size;
|
|
uint32_t cus_size;
|
|
iot_sg_sta_upgrade_info_t *upgrade_info;
|
|
|
|
uint32_t block_size = IOT_SG_UPGRADE_MAX_BLOCK_SIZE;
|
|
uint32_t pib_read_only = iot_upgrade_get_pib_ro_size();
|
|
upgrade_info = &p_sg_glb->desc.sta->upgrade_info;
|
|
if (upgrade_info->calc_crc) {
|
|
return upgrade_info->calc_crc;
|
|
}
|
|
|
|
pib_size = iot_upgrade_get_pib_len();
|
|
fw_size = iot_upgrade_get_fw_len();
|
|
cus_size = iot_upgrade_get_cus_len();
|
|
|
|
iot_sg_printf("to calc crc\n");
|
|
/* calc header crc */
|
|
offset = 0;
|
|
if (!upgrade_info->cache) {
|
|
goto err_exit;
|
|
}
|
|
|
|
ptr = iot_pkt_data(upgrade_info->cache);
|
|
if (align_size >= upgrade_info->block_size) {
|
|
crc = iot_getcrc32_update(crc, ptr, upgrade_info->block_size);
|
|
len = (align_size - upgrade_info->block_size) / upgrade_info->block_size;
|
|
os_mem_set(ptr, iot_pkg_get_pad_value(), upgrade_info->block_size);
|
|
while (len) {
|
|
/* calc crc for padding */
|
|
crc = iot_getcrc32_update(crc, ptr, upgrade_info->block_size);
|
|
len--;
|
|
}
|
|
len = (align_size - upgrade_info->block_size) % upgrade_info->block_size;
|
|
crc = iot_getcrc32_update(crc, ptr, len);
|
|
} else {
|
|
crc = iot_getcrc32_update(crc, ptr, align_size);
|
|
}
|
|
|
|
if (pib_size) {
|
|
/* calc pib crc */
|
|
offset = 0;
|
|
len = pib_read_only / block_size;
|
|
/* calc pib read only part */
|
|
while (len) {
|
|
if (iot_pkg_upgrade_read(ptr, block_size, offset,
|
|
UPGRADE_DATA_TYPE_PIB, 0)) {
|
|
goto err_exit;
|
|
}
|
|
|
|
crc = iot_getcrc32_update(crc, ptr, block_size);
|
|
offset += block_size;
|
|
len--;
|
|
}
|
|
len = pib_read_only % block_size;
|
|
if (iot_pkg_upgrade_read(ptr, iot_sg_sta_get_align(len, 4), offset,
|
|
UPGRADE_DATA_TYPE_PIB, 0)) {
|
|
goto err_exit;
|
|
}
|
|
crc = iot_getcrc32_update(crc, ptr, len);
|
|
offset += len;
|
|
|
|
/* calc pib read write part */
|
|
file_len = pib_size;
|
|
len = (file_len - pib_read_only) / block_size;
|
|
os_mem_set(ptr, iot_pkg_get_pad_value(), block_size);
|
|
while (len) {
|
|
crc = iot_getcrc32_update(crc, ptr, block_size);
|
|
offset += block_size;
|
|
len--;
|
|
}
|
|
len = (file_len - pib_read_only) % block_size;
|
|
crc = iot_getcrc32_update(crc, ptr, len);
|
|
offset += len;
|
|
|
|
if (fw_size) {
|
|
/* crc for pib padding content */
|
|
file_block_len = iot_sg_sta_get_align(file_len, align_size);
|
|
len = (file_block_len - file_len) / block_size;
|
|
while (len) {
|
|
crc = iot_getcrc32_update(crc, ptr, block_size);
|
|
offset += block_size;
|
|
len--;
|
|
}
|
|
len = (file_block_len - file_len) % block_size;
|
|
crc = iot_getcrc32_update(crc, ptr, len);
|
|
}
|
|
}
|
|
/* calc fw crc */
|
|
if (fw_size) {
|
|
offset = 0;
|
|
file_len = fw_size;
|
|
len = file_len / block_size;
|
|
while (len) {
|
|
if (iot_pkg_upgrade_read(ptr, block_size, offset, UPGRADE_DATA_TYPE_FW,
|
|
0)) {
|
|
goto err_exit;
|
|
}
|
|
crc = iot_getcrc32_update(crc, ptr, block_size);
|
|
offset += block_size;
|
|
len--;
|
|
}
|
|
len = file_len % block_size;
|
|
if (iot_pkg_upgrade_read(ptr, iot_sg_sta_get_align(len, 4), offset,
|
|
UPGRADE_DATA_TYPE_FW, 0)) {
|
|
goto err_exit;
|
|
}
|
|
crc = iot_getcrc32_update(crc, ptr, len);
|
|
|
|
if (cus_size) {
|
|
/* crc for fw padding content */
|
|
file_block_len = iot_sg_sta_get_align(file_len, align_size);
|
|
len = (file_block_len - file_len) / block_size;
|
|
os_mem_set(ptr, iot_pkg_get_pad_value(), block_size);
|
|
while (len) {
|
|
crc = iot_getcrc32_update(crc, ptr, block_size);
|
|
offset += block_size;
|
|
len--;
|
|
}
|
|
len = (file_block_len - file_len) % block_size;
|
|
crc = iot_getcrc32_update(crc, ptr, len);
|
|
}
|
|
}
|
|
/* calc cus crc */
|
|
if (cus_size) {
|
|
offset = 0;
|
|
file_len = cus_size;
|
|
len = file_len / block_size;
|
|
while (len) {
|
|
if (iot_pkg_upgrade_read(ptr, block_size, offset,
|
|
UPGRADE_DATA_TYPE_CUS, 0)) {
|
|
goto err_exit;
|
|
}
|
|
crc = iot_getcrc32_update(crc, ptr, block_size);
|
|
offset += block_size;
|
|
len--;
|
|
}
|
|
len = file_len % block_size;
|
|
if (iot_pkg_upgrade_read(ptr, iot_sg_sta_get_align(len, 4), offset,
|
|
UPGRADE_DATA_TYPE_CUS, 0)) {
|
|
goto err_exit;
|
|
}
|
|
crc = iot_getcrc32_update(crc, ptr, len);
|
|
}
|
|
|
|
crc ^= 0xFFFFFFFF;
|
|
|
|
iot_sg_printf("sg_upgrade: calc crc = 0x%08X, recv crc = 0x%08X\n",
|
|
crc, upgrade_info->file_crc);
|
|
if (crc != upgrade_info->file_crc) {
|
|
goto err_exit;
|
|
}
|
|
|
|
return crc;
|
|
|
|
err_exit:
|
|
/* failed to calcluete the CRC. */
|
|
iot_sg_printf("sg_upgrade: calc crc = 0x%08X\n", crc);
|
|
return upgrade_info->file_crc;
|
|
}
|
|
|
|
static void iot_sg_sta_save_to_flash()
|
|
{
|
|
uint32_t other_part;
|
|
iot_sg_sta_upgrade_info_t *upgrade_info;
|
|
upgrade_info = &p_sg_glb->desc.sta->upgrade_info;
|
|
upgrade_info->calc_crc = iot_sg_sta_get_crc();
|
|
other_part = iot_upgrade_get_another_part(upgrade_info->current_part);
|
|
iot_sg_printf("sg_upgrade: cur_part = %d, save data to part = %d\n",
|
|
upgrade_info->current_part, other_part);
|
|
iot_upgrade_save_trail_run_dur(other_part, upgrade_info->trail_run_dur);
|
|
iot_upgrade_save_fw_crc(other_part, upgrade_info->file_crc);
|
|
iot_upgrade_save_fw_len(other_part, upgrade_info->file_size);
|
|
iot_upgrade_save_fw_blksize(other_part, upgrade_info->block_size);
|
|
}
|
|
|
|
static void iot_sg_sta_upgrade_goto_state(uint16_t new_state)
|
|
{
|
|
iot_sg_sta_upgrade_info_t *p_info = &p_sg_glb->desc.sta->upgrade_info;
|
|
uint16_t pre_state = p_info->state;
|
|
uint8_t rpt_flag = 0;
|
|
uint8_t rpt_result = 0;
|
|
|
|
if (p_info->state != new_state) {
|
|
iot_sg_printf("sg_upgrade: state from %d to %d.\n", p_info->state,
|
|
new_state);
|
|
p_info->state = new_state;
|
|
if (IOT_SG_STA_UPGRADE_ST_IDLE == new_state) {
|
|
if (p_info->cache) {
|
|
iot_pkt_free(p_info->cache);
|
|
p_info->cache = NULL;
|
|
}
|
|
/* upgrade stop */
|
|
rpt_flag = 1;
|
|
} else if (IOT_SG_STA_UPGRADE_ST_IDLE == pre_state) {
|
|
/* upgrade start */
|
|
rpt_flag = 1;
|
|
rpt_result = 1;
|
|
}
|
|
}
|
|
if (rpt_flag) {
|
|
iot_sg_ext_upgrade_state_rpt_to_cusapp(rpt_result);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief: init upgrading module
|
|
*/
|
|
void iot_sg_sta_upgrade_init()
|
|
{
|
|
uint32_t part;
|
|
uint32_t exit_reason;
|
|
iot_upg_bp_resume_info_t resume_info = { 0 };
|
|
|
|
iot_sg_sta_upgrade_info_t *upgrade_info = NULL;
|
|
upgrade_info = &p_sg_glb->desc.sta->upgrade_info;
|
|
if (upgrade_info->state != IOT_SG_STA_UPGRADE_ST_INVALID) {
|
|
/* only init when in INVALID state */
|
|
iot_sg_printf("sg_upgrade: don't init again.\n");
|
|
return;
|
|
}
|
|
|
|
if (iot_upgrade_get_part(&part)) {
|
|
/* cannot upgrade because failed to read partition info */
|
|
iot_sg_printf("sg_upgrade: failed to get current boot part.\n");
|
|
return;
|
|
}
|
|
|
|
exit_reason = iot_upgrade_get_upgrade_status();
|
|
if (exit_reason != 0xff) {
|
|
upgrade_info->exit_reason = (uint8_t)exit_reason;
|
|
}
|
|
upgrade_info->current_part = part;
|
|
upgrade_info->trail_run_dur = iot_upgrade_get_trail_run_dur(part);
|
|
upgrade_info->current_len = iot_upgrade_get_fw_size(part);
|
|
if (upgrade_info->current_len == 0) {
|
|
upgrade_info->current_len = iot_upgrade_get_backup_len();
|
|
iot_upgrade_save_fw_len(part, upgrade_info->current_len);
|
|
}
|
|
|
|
upgrade_info->current_crc = iot_upgrade_get_fw_crc(part);
|
|
if (upgrade_info->current_crc == 0) {
|
|
upgrade_info->current_crc = iot_upgrade_get_backup_crc();
|
|
iot_upgrade_save_fw_crc(part, upgrade_info->current_crc);
|
|
}
|
|
iot_dbglog_input(IOT_SMART_GRID_MID, DBGLOG_ERR,
|
|
IOT_SG_STA_UPGRADE_DBG_ID, 2, 0xff00|part, upgrade_info->current_crc);
|
|
|
|
upgrade_info->current_bk_size = iot_upgrade_get_fw_blksize(part);
|
|
if (upgrade_info->current_bk_size == 0) {
|
|
upgrade_info->current_bk_size = IOT_SG_UPGRADE_MAX_BLOCK_SIZE;
|
|
}
|
|
|
|
upgrade_info->block_cnt = (uint16_t)((upgrade_info->current_len +
|
|
upgrade_info->current_bk_size - 1) / upgrade_info->current_bk_size);
|
|
|
|
iot_sg_printf("%s: part = %lu, len = %lu, crc = 0x%08X, trail run dur = "
|
|
"%lu, block size = %lu,\n", __FUNCTION__, upgrade_info->current_part,
|
|
upgrade_info->current_len, upgrade_info->current_crc,
|
|
upgrade_info->trail_run_dur, upgrade_info->current_bk_size);
|
|
if (upgrade_info->trail_run_dur) {
|
|
iot_sg_sta_upgrade_goto_state(IOT_SG_STA_UPGRADE_ST_TRAIL_RUN);
|
|
//clear the trail run time
|
|
iot_upgrade_save_trail_run_dur(part, 0);
|
|
|
|
/* start the timer for upgrading time window */
|
|
iot_sg_sta_start_upgrade_timer(upgrade_info->trail_run_dur * 1000);
|
|
} else {
|
|
if (iot_upgrade_get_bp_resume_info(UPGRADE_GET_METHOD_SG,
|
|
&resume_info) == ERR_OK) {
|
|
if ((resume_info.state == UPGRADE_BP_STATE_RECV_DONE) &&
|
|
(!resume_info.ext_upgrade_flag)) {
|
|
upgrade_info->file_crc = resume_info.file_crc;
|
|
upgrade_info->file_size = resume_info.file_len;
|
|
iot_sg_sta_save_to_flash();
|
|
iot_pkg_upgrade_commit(0);
|
|
iot_pkg_upgrade_reset();
|
|
}
|
|
}
|
|
iot_sg_sta_upgrade_goto_state(IOT_SG_STA_UPGRADE_ST_IDLE);
|
|
}
|
|
}
|
|
|
|
void iot_sg_sta_reset_upgrade_info(iot_sg_sta_upgrade_info_t *upgrade_info)
|
|
{
|
|
timer_id_t upgrade_timer;
|
|
timer_id_t ext_dev_upgrade_timer;
|
|
uint32_t current_part;
|
|
uint32_t len;
|
|
uint32_t crc;
|
|
uint32_t block_size;
|
|
uint32_t block_cnt;
|
|
uint32_t file_size;
|
|
uint8_t exit_reason;
|
|
|
|
block_size = upgrade_info->block_size;
|
|
file_size = upgrade_info->file_size;
|
|
block_cnt = upgrade_info->block_cnt;
|
|
len = upgrade_info->current_len;
|
|
crc = upgrade_info->current_crc;
|
|
current_part = upgrade_info->current_part;
|
|
upgrade_timer = upgrade_info->upgrade_timer;
|
|
ext_dev_upgrade_timer = upgrade_info->ext_dev_upgrade_timer;
|
|
exit_reason = upgrade_info->exit_reason;
|
|
os_mem_set(upgrade_info, 0, sizeof(*upgrade_info));
|
|
/* cert test case 3.3.6.4 - keep last upgrade info after upgrade stopped
|
|
* for upcoming query from CCO case.
|
|
*/
|
|
upgrade_info->block_size = block_size;
|
|
upgrade_info->file_size = file_size;
|
|
upgrade_info->block_cnt = block_cnt;
|
|
upgrade_info->upgrade_timer = upgrade_timer;
|
|
upgrade_info->ext_dev_upgrade_timer = ext_dev_upgrade_timer;
|
|
upgrade_info->current_part = current_part;
|
|
upgrade_info->current_len = len;
|
|
upgrade_info->current_crc = crc;
|
|
upgrade_info->exit_reason = exit_reason;
|
|
iot_sg_sta_upgrade_goto_state(IOT_SG_STA_UPGRADE_ST_IDLE);
|
|
iot_plc_led_request(IOT_PLC_LED_UPGRADE_OFF);
|
|
}
|
|
|
|
void iot_sg_sta_upgrade_clear(uint32_t upgrade_id, uint32_t cancel_commit)
|
|
{
|
|
iot_sg_sta_upgrade_info_t *upgrade_info = NULL;
|
|
upgrade_info = &p_sg_glb->desc.sta->upgrade_info;
|
|
iot_sg_printf("sg_upgrade: %s. id = 0x%02X, cancel_commit = %d\n",
|
|
__FUNCTION__, upgrade_info->upgrade_id, cancel_commit);
|
|
|
|
/* clear upgrading status if it's not in INVALID state */
|
|
if (upgrade_info->state != IOT_SG_STA_UPGRADE_ST_INVALID &&
|
|
upgrade_info->state != IOT_SG_STA_UPGRADE_ST_IDLE) {
|
|
if (upgrade_id && upgrade_id != upgrade_info->upgrade_id) {
|
|
return;
|
|
}
|
|
iot_sg_sta_stop_upgrade_timer();
|
|
iot_pkg_upgrade_cancel_commit(upgrade_id, cancel_commit);
|
|
iot_sg_sta_reset_upgrade_info(upgrade_info);
|
|
iot_sg_ext_dev_reset_upgrade_info();
|
|
}
|
|
}
|
|
|
|
uint32_t iot_sg_sta_recv_all_block()
|
|
{
|
|
iot_sg_sta_upgrade_info_t *p_info = &p_sg_glb->desc.sta->upgrade_info;
|
|
iot_pkg_upg_sts_rst_t rst = {0};
|
|
iot_pkg_upg_sts_src_t src = {0};
|
|
uint32_t recv_block_count = 0;
|
|
uint32_t byte_count = 0;
|
|
|
|
src.id = p_info->upgrade_id;
|
|
src.block_size = p_info->block_size;
|
|
src.block_cnt = p_info->block_cnt;
|
|
src.block_index = 0;
|
|
if (ERR_OK != iot_pkg_upgrade_query_state(&rst, &src)) {
|
|
/* failed to query */
|
|
return 0;
|
|
}
|
|
|
|
/* get byte count of the bitmap */
|
|
byte_count = rst.block_cnt >> 3;
|
|
for (uint32_t i = 0; i < byte_count; ++i) {
|
|
if (rst.bitmap[i] != 0xFF) {
|
|
break;
|
|
}
|
|
|
|
recv_block_count += 8;
|
|
}
|
|
|
|
if ((byte_count << 3) != p_info->block_cnt) {
|
|
/* less than 8 block in the last block */
|
|
for (uint32_t i = 0; i < 8; ++i) {
|
|
if (rst.bitmap[byte_count-1] & (1 << i)) {
|
|
recv_block_count += 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
iot_sg_printf("upgrade: total block cnt = 0n%d, recv block cnt = %d\n",
|
|
p_info->block_cnt, recv_block_count);
|
|
if (recv_block_count == p_info->block_cnt) {
|
|
iot_sg_sta_renew_exit_reason_code(IOT_SG_STA_UPGRADE_EXIT_NORMAL);
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief: timer handler for upgrading
|
|
*/
|
|
void iot_sg_sta_upgrade_timer_handler()
|
|
{
|
|
iot_sg_sta_upgrade_info_t *p_info = &p_sg_glb->desc.sta->upgrade_info;
|
|
iot_sg_printf("sg_upgrade: sta upgrade timer. state = %d\n",
|
|
p_info->state);
|
|
switch (p_info->state) {
|
|
case IOT_SG_STA_UPGRADE_ST_INVALID:
|
|
case IOT_SG_STA_UPGRADE_ST_IDLE:
|
|
{
|
|
/* idle state won't receive any message */
|
|
}
|
|
break;
|
|
case IOT_SG_STA_UPGRADE_ST_RECEIVE:
|
|
{
|
|
if (iot_sg_sta_recv_all_block() &&
|
|
(!p_info->ext_dev_need_upgrade_flag)) {
|
|
iot_sg_printf("sg upgrade: trans done. commit.\n");
|
|
iot_dbglog_input(IOT_SMART_GRID_MID, DBGLOG_ERR,
|
|
IOT_SG_STA_UPGRADE_DBG_ID, 2, 2, 0);
|
|
iot_sg_sta_save_to_flash();
|
|
iot_pkg_upgrade_commit(p_info->upgrade_id);
|
|
iot_pkg_upgrade_reset();
|
|
} else {
|
|
iot_sg_printf("sg upgrade: trans not done. clear.\n");
|
|
iot_sg_sta_upgrade_clear(p_info->upgrade_id, 1);
|
|
}
|
|
}
|
|
break;
|
|
case IOT_SG_STA_UPGRADE_ST_RECV_DONE:
|
|
{
|
|
iot_sg_printf("sg upgrade: upgrade commit, skip: %d ext upgrade:%d\n",
|
|
p_info->skip, p_info->ext_dev_need_upgrade_flag);
|
|
iot_dbglog_input(IOT_SMART_GRID_MID, DBGLOG_ERR,
|
|
IOT_SG_STA_UPGRADE_DBG_ID, 2, 3, p_info->skip);
|
|
if ((!p_info->skip) && (!p_info->ext_dev_need_upgrade_flag)) {
|
|
iot_sg_sta_save_to_flash();
|
|
iot_pkg_upgrade_commit(p_info->upgrade_id);
|
|
iot_upgrade_reset();
|
|
} else {
|
|
iot_sg_printf("sg upgrade: skip upgrade, clean upgrade.\n");
|
|
iot_sg_sta_upgrade_clear(p_info->upgrade_id, 1);
|
|
}
|
|
}
|
|
break;
|
|
case IOT_SG_STA_UPGRADE_ST_EXECUTE:
|
|
{
|
|
iot_sg_printf("sg upgrade: upgrade execute, skip: %d\n", p_info->skip);
|
|
iot_dbglog_input(IOT_SMART_GRID_MID, DBGLOG_ERR,
|
|
IOT_SG_STA_UPGRADE_DBG_ID, 2, 4, p_info->skip);
|
|
if (!p_info->ext_dev_need_upgrade_flag) {
|
|
if (!p_info->skip) {
|
|
iot_sg_sta_save_to_flash();
|
|
iot_pkg_upgrade_commit(p_info->upgrade_id);
|
|
iot_upgrade_reset();
|
|
} else {
|
|
iot_sg_sta_reset_upgrade_info(p_info);
|
|
}
|
|
} else {
|
|
iot_sg_printf("sg upgrade: external upgrade timeout.\n");
|
|
iot_sg_sta_upgrade_clear(p_info->upgrade_id, 0);
|
|
}
|
|
}
|
|
break;
|
|
case IOT_SG_STA_UPGRADE_ST_TRAIL_RUN:
|
|
{
|
|
/* trail run is done. */
|
|
iot_sg_printf("sg upgrade: trail run timeout. link_ready = %d\n",
|
|
p_sg_glb->plc_state.link_ready);
|
|
iot_dbglog_input(IOT_SMART_GRID_MID, DBGLOG_ERR,
|
|
IOT_SG_UPGRADE_TRAIL_RUN_TIMEOUT, 1,
|
|
p_sg_glb->plc_state.link_ready);
|
|
|
|
iot_dbglog_input(IOT_SMART_GRID_MID, DBGLOG_ERR,
|
|
IOT_SG_STA_UPGRADE_DBG_ID, 2, 1, p_sg_glb->plc_state.link_ready);
|
|
if (p_sg_glb->plc_state.link_ready) {
|
|
iot_sg_sta_upgrade_goto_state(IOT_SG_STA_UPGRADE_ST_IDLE);
|
|
iot_sg_sta_upgrade_clear(p_info->upgrade_id, 0);
|
|
} else {
|
|
/* STA failed to join network in trail run duration,
|
|
* switch back to status before upgrading.
|
|
*/
|
|
iot_upgrade_switch_part();
|
|
iot_upgrade_reset();
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
uint32_t iot_sg_sta_handle_upgrade_data(uint32_t id, uint16_t block_size,
|
|
uint32_t seq, uint8_t *data, iot_pkt_t *pkt, uint8_t rsp_flag)
|
|
{
|
|
uint32_t file_dev_type;
|
|
uint32_t file_vendor_id;
|
|
uint32_t local_vendor_id;
|
|
uint32_t result;
|
|
uint32_t reason = 0;
|
|
uint32_t offset;
|
|
iot_sg_sta_upgrade_info_t *upgrade_info;
|
|
|
|
upgrade_info = &p_sg_glb->desc.sta->upgrade_info;
|
|
offset = seq * upgrade_info->block_size;
|
|
|
|
iot_sg_printf("sg_upgrade: received seq = %d. block size = %d. %d/%d\n",
|
|
seq, block_size, offset + block_size,
|
|
upgrade_info->file_size);
|
|
|
|
if (IOT_SG_STA_UPGRADE_ST_RECEIVE != upgrade_info->state) {
|
|
/* process upgrading data only in RECV state */
|
|
reason = 1;
|
|
goto err_exit;
|
|
}
|
|
|
|
if (id != upgrade_info->upgrade_id) {
|
|
if (upgrade_info->session_type == IOT_SG_STA_UPGRADE_SESSION_TYPE_NW) {
|
|
iot_sg_sta_upgrade_on_join(1);
|
|
}
|
|
reason = 2;
|
|
goto err_exit;
|
|
}
|
|
|
|
if (iot_pkg_upgrade_is_set_bit(seq)) {
|
|
/* block was processed before */
|
|
reason = 3;
|
|
goto err_exit;
|
|
}
|
|
|
|
if (seq == 0) {
|
|
/* it's the first block */
|
|
iot_start_rst_t rst = {0};
|
|
file_dev_type = iot_get_file_type(data);
|
|
|
|
if (IOT_FILE_TYPE_CCO == file_dev_type) {
|
|
iot_sg_printf("sg_upgrade: invalid file, it's cco file\n");
|
|
reason = 4;
|
|
goto err_skip;
|
|
} else if (IOT_FILE_TYPE_EXT_DEV == file_dev_type) {
|
|
upgrade_info->ext_dev_need_upgrade_flag = 1;
|
|
iot_sg_printf("sg_upgrade: upgrade external device\n");
|
|
} else if (IOT_FILE_TYPE_STA != file_dev_type) {
|
|
iot_sg_printf("sg_upgrade: invalid file type: %04x. skip upgrade\n",
|
|
file_dev_type);
|
|
reason = 5;
|
|
goto err_skip;
|
|
}
|
|
|
|
file_vendor_id = iot_get_vendor_id(data);
|
|
local_vendor_id = iot_sg_get_vendor_id();
|
|
if (local_vendor_id != file_vendor_id) {
|
|
iot_sg_printf("sg_upgrade: vendor_id expect %04X but %04X.\n",
|
|
local_vendor_id, file_vendor_id);
|
|
reason = 6;
|
|
goto err_skip;
|
|
}
|
|
|
|
if (upgrade_info->session_type == IOT_SG_STA_UPGRADE_SESSION_TYPE_NW) {
|
|
/* nw start cmd dones't have block_size info. */
|
|
/* update block_size when receive the 1st block for nw. */
|
|
upgrade_info->block_size = block_size;
|
|
}
|
|
|
|
if (ERR_OK == iot_pkg_upgrade_start(&rst, upgrade_info->upgrade_id,
|
|
upgrade_info->block_size, upgrade_info->file_size,
|
|
upgrade_info->file_crc, upgrade_info->block_cnt,
|
|
upgrade_info->ext_dev_need_upgrade_flag, data)) {
|
|
if (!upgrade_info->cache) {
|
|
upgrade_info->cache = iot_pkt_alloc(
|
|
IOT_SG_UPGRADE_MAX_BLOCK_SIZE, IOT_SMART_GRID_MID);
|
|
if (!upgrade_info->cache) {
|
|
iot_sg_printf("sg_upgrade: iot pkt malloc fail.\n");
|
|
reason = 7;
|
|
goto err_exit;
|
|
}
|
|
}
|
|
/* save header to cache */
|
|
os_mem_cpy(iot_pkt_data(upgrade_info->cache), data, block_size);
|
|
iot_pkt_put(upgrade_info->cache, block_size);
|
|
upgrade_info->header_recved = 1;
|
|
iot_sg_printf("sg_upgrade: start upgrade OK.\n");
|
|
} else {
|
|
iot_sg_printf("sg_upgrade: start upgrade failed.\n");
|
|
reason = 8;
|
|
goto err_exit;
|
|
}
|
|
}
|
|
|
|
{
|
|
/* write data to flash */
|
|
iot_trans_cmd_t trans = {0};
|
|
iot_pkt_set_data(pkt, data);
|
|
iot_pkt_set_tail(pkt, data + block_size);
|
|
|
|
trans.id = upgrade_info->upgrade_id;
|
|
trans.block_num = seq;
|
|
trans.crc_flag = 0;
|
|
trans.data = pkt;
|
|
trans.data_type = UPGRADE_DATA_TYPE_PKG;
|
|
result = iot_pkg_upgrade_trans(&trans);
|
|
iot_sg_printf("sg_upgrade: trans result = %d. block %d. size = %d\n",
|
|
result, trans.block_num, block_size);
|
|
}
|
|
upgrade_info->rec_blk_cnt++;
|
|
if ((upgrade_info->rec_blk_cnt >= upgrade_info->block_cnt) &&
|
|
(upgrade_info->session_type == IOT_SG_STA_UPGRADE_SESSION_TYPE_645 ||
|
|
upgrade_info->session_type == IOT_SG_STA_UPGRADE_SESSION_TYPE_DRV)) {
|
|
iot_sg_sta_handle_upgrade_execute(id, 0, 0, 0);
|
|
}
|
|
result = IOT_PLC_UPGRADE_OK;
|
|
goto out;
|
|
err_skip:
|
|
if (0 == upgrade_info->skip) {
|
|
upgrade_info->skip = 1;
|
|
iot_sg_sta_renew_exit_reason_code(IOT_SG_STA_UPGRADE_EXIT_MISMATCH);
|
|
iot_sg_sta_upgrade_goto_state(IOT_SG_STA_UPGRADE_ST_RECV_DONE);
|
|
}
|
|
err_exit:
|
|
result = IOT_PLC_UPGRADE_ERR_UNKNOWN;
|
|
iot_pkt_free(pkt);
|
|
iot_sg_printf("sg_upgrade: drop data. reason = %d.\n", reason);
|
|
out:
|
|
if ((upgrade_info->session_type == IOT_SG_STA_UPGRADE_SESSION_TYPE_NW) &&
|
|
rsp_flag) {
|
|
iot_sg_sta_nw_send_upgrade_data_ack(id, result);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
uint32_t iot_sg_sta_handle_start_upgrade(uint32_t id, uint16_t window,
|
|
uint16_t block_size, uint32_t file_size, uint16_t block_cnt,
|
|
uint32_t file_crc, uint8_t rsp_flag, uint8_t session_type)
|
|
{
|
|
iot_sg_sta_upgrade_info_t *upgrade_info;
|
|
uint8_t result = IOT_PLC_UPGRADE_OK;
|
|
|
|
upgrade_info = &p_sg_glb->desc.sta->upgrade_info;
|
|
|
|
iot_sg_printf("sg_upgrade: %s. id = 0x%08X, size = %d, block_size = %d, "
|
|
"block_cnt = %d, st = %d, crc = 0x%08X\n", __FUNCTION__, id, file_size,
|
|
block_size, block_cnt, upgrade_info->state, file_crc);
|
|
|
|
if (upgrade_info->state != IOT_SG_STA_UPGRADE_ST_IDLE) {
|
|
if (session_type == IOT_SG_STA_UPGRADE_SESSION_TYPE_NW) {
|
|
if (upgrade_info->upgrade_id == id) {
|
|
if ((upgrade_info->block_size != block_size) ||
|
|
(upgrade_info->file_size != file_size) ||
|
|
(upgrade_info->block_cnt != block_cnt) ||
|
|
(upgrade_info->file_crc != file_crc)) {
|
|
result = IOT_PLC_UPGRADE_STATE_ERR;
|
|
goto out;
|
|
}
|
|
goto exit_label;
|
|
} else {
|
|
iot_sg_sta_upgrade_on_join(1);
|
|
}
|
|
} else if ((upgrade_info->upgrade_id != id) ||
|
|
(upgrade_info->block_size != block_size) ||
|
|
(upgrade_info->file_size != file_size) ||
|
|
(upgrade_info->block_cnt != block_cnt) ||
|
|
(upgrade_info->file_crc != file_crc)) {
|
|
/* ignore start upgrade command if not id IDLE state. */
|
|
result = IOT_PLC_UPGRADE_STATE_ERR;
|
|
goto out;
|
|
} else {
|
|
goto exit_label;
|
|
}
|
|
}
|
|
|
|
if (session_type == IOT_SG_STA_UPGRADE_SESSION_TYPE_GW &&
|
|
0 == iot_sg_sta_gw_is_valid_block_size(block_size)) {
|
|
/* block size checking only apply to guowang upgrading. */
|
|
result = IOT_PLC_UPGRADE_ERR_BLOCK_SIZE;
|
|
goto exit_label;
|
|
}
|
|
|
|
if (p_sg_glb->plc_state.cert_test_detected == 0 &&
|
|
upgrade_info->current_crc == file_crc) {
|
|
result = IOT_PLC_UPGRADE_ERR_SAME_VERSION;
|
|
if (0 == upgrade_info->skip) {
|
|
upgrade_info->skip = 1;
|
|
upgrade_info->upgrade_id = id;
|
|
upgrade_info->session_type = session_type;
|
|
iot_sg_sta_renew_exit_reason_code(IOT_SG_STA_UPGRADE_EXIT_SAME_VER);
|
|
iot_sg_sta_upgrade_goto_state(IOT_SG_STA_UPGRADE_ST_RECV_DONE);
|
|
}
|
|
goto exit_label;
|
|
}
|
|
|
|
/* set LED to show upgrading state */
|
|
iot_plc_led_request(IOT_PLC_LED_UPGRADE_ON);
|
|
|
|
iot_sg_sta_upgrade_goto_state(IOT_SG_STA_UPGRADE_ST_RECEIVE);
|
|
upgrade_info->file_size = file_size;
|
|
upgrade_info->file_crc = file_crc;
|
|
upgrade_info->calc_crc = 0;
|
|
upgrade_info->upgrade_time_win = window;
|
|
upgrade_info->upgrade_id = id;
|
|
upgrade_info->block_size = block_size;
|
|
upgrade_info->block_cnt = block_cnt;
|
|
upgrade_info->rec_blk_cnt = 0;
|
|
upgrade_info->skip = 0;
|
|
upgrade_info->header_recved = 0;
|
|
upgrade_info->session_type = session_type;
|
|
iot_sg_ext_dev_reset_upgrade_info();
|
|
|
|
/* start the timer for upgrading time window */
|
|
iot_sg_sta_start_upgrade_timer(upgrade_info->upgrade_time_win * 60 * 1000);
|
|
|
|
exit_label:
|
|
if (rsp_flag) {
|
|
iot_sg_sta_send_start_ack(id, IOT_PLC_MSG_TYPE_UNICAST, result);
|
|
}
|
|
out:
|
|
return result;
|
|
}
|
|
|
|
iot_pkt_t *iot_sg_sta_get_recv_bitmap(uint32_t start_seq, uint16_t cnt)
|
|
{
|
|
iot_pkt_t *bitmap_pkt = NULL;
|
|
uint8_t *bm;
|
|
iot_sg_sta_upgrade_info_t *upgrade_info;
|
|
uint32_t start_sn;
|
|
uint32_t start_byte;
|
|
uint32_t bm_byte_size;
|
|
uint32_t ret_bm_byte_size;
|
|
uint32_t pad_bit_cnt;
|
|
uint32_t bm_byte_cnt;
|
|
uint32_t i;
|
|
uint8_t cnt_remainder = 0;
|
|
|
|
/* query upgrade bitmap */
|
|
iot_pkg_upg_sts_rst_t rst = {0};
|
|
iot_pkg_upg_sts_src_t src = {0};
|
|
|
|
upgrade_info = &p_sg_glb->desc.sta->upgrade_info;
|
|
if (IOT_SG_STA_QUERY_ALL_BLOCK == cnt) {
|
|
/* return all blocks */
|
|
cnt = (uint16_t)upgrade_info->block_cnt;
|
|
start_sn = 0;
|
|
start_byte = 0;
|
|
bm_byte_size = ((cnt + 7) >> 3);
|
|
ret_bm_byte_size = bm_byte_size;
|
|
pad_bit_cnt = 0;
|
|
bm_byte_cnt = 0;
|
|
} else {
|
|
/* make start seq align to 8, bm_byte_size align to 1 byte. */
|
|
start_byte = start_seq >> 3;
|
|
start_sn = start_byte << 3;
|
|
bm_byte_size = ((cnt + 7 + (start_seq - start_sn)) >> 3);
|
|
ret_bm_byte_size = ((cnt + 7) >> 3);
|
|
cnt_remainder = cnt & 0x07;
|
|
if (start_seq == start_sn) {
|
|
pad_bit_cnt = 0;
|
|
} else {
|
|
pad_bit_cnt = 8 - (start_seq - start_sn);
|
|
}
|
|
}
|
|
iot_sg_printf("%s cnt is : %lu\n", __FUNCTION__, ret_bm_byte_size);
|
|
iot_sg_printf("%s current_len : %lu current_bk_size : %lu\n,",
|
|
__FUNCTION__, upgrade_info->current_len, upgrade_info->current_bk_size);
|
|
bitmap_pkt = iot_pkt_alloc(bm_byte_size, IOT_SMART_GRID_MID);
|
|
if (bitmap_pkt == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
bm = iot_pkt_data(bitmap_pkt);
|
|
|
|
if (upgrade_info->skip) {
|
|
/* if STA shall skip upgrading, STA enter DONE state and
|
|
* all bits in bitmap will be set to 1.
|
|
*/
|
|
os_mem_set(bm, 0xff, ret_bm_byte_size);
|
|
iot_pkt_put(bitmap_pkt, ret_bm_byte_size);
|
|
return bitmap_pkt;
|
|
} else if (0 == upgrade_info->header_recved) {
|
|
/* received data is zero, lower upgrade module may not be ready for
|
|
* querying bitmap.
|
|
*/
|
|
os_mem_set(bm, 0x00, ret_bm_byte_size);
|
|
iot_pkt_put(bitmap_pkt, ret_bm_byte_size);
|
|
return bitmap_pkt;
|
|
}
|
|
|
|
src.id = upgrade_info->upgrade_id;
|
|
src.block_size = upgrade_info->block_size;
|
|
src.block_index = start_sn;
|
|
src.block_cnt = cnt + (start_seq - start_sn);
|
|
|
|
if (ERR_OK == iot_pkg_upgrade_query_state(&rst, &src)) {
|
|
bm_byte_cnt = (uint16_t)(rst.block_cnt >> 3);
|
|
if (bm_byte_cnt) {
|
|
os_mem_cpy(bm, rst.bitmap, bm_byte_cnt);
|
|
if (pad_bit_cnt) {
|
|
/* move all bytes (8-pad_bit_cnt) bit forward except the last one */
|
|
i = 0;
|
|
do {
|
|
bm[i] >>= (8 - pad_bit_cnt);
|
|
if (i < (bm_byte_cnt - 1)) {
|
|
bm[i] |= (bm[i + 1] << (pad_bit_cnt));
|
|
}
|
|
++i;
|
|
} while(i < bm_byte_cnt);
|
|
}
|
|
if (cnt_remainder) {
|
|
bm[ret_bm_byte_size - 1] <<= (8 - cnt_remainder);
|
|
bm[ret_bm_byte_size - 1] >>= (8 - cnt_remainder);
|
|
}
|
|
}
|
|
|
|
iot_pkt_put(bitmap_pkt, ret_bm_byte_size);
|
|
iot_sg_printf("upgrade: bm byte size = %d, start block = %d, len = %d,"
|
|
" cnt = %d.\n", bm_byte_cnt, start_seq, ret_bm_byte_size, cnt);
|
|
for (i = 0; i < ret_bm_byte_size; ++i) {
|
|
if (bm[i] != 0xFF || i + 1 == ret_bm_byte_size) {
|
|
iot_sg_printf("upgrade: bm[%d] = %02X\n", i, bm[i]);
|
|
}
|
|
}
|
|
} else {
|
|
iot_pkt_free(bitmap_pkt);
|
|
bitmap_pkt = NULL;
|
|
}
|
|
|
|
return bitmap_pkt;
|
|
}
|
|
|
|
void iot_sg_sta_handle_upgrade_query_status(uint32_t id, uint32_t start_seq,
|
|
uint16_t cnt, uint8_t session_type)
|
|
{
|
|
iot_sg_sta_upgrade_info_t *upgrade_info;
|
|
iot_pkt_t *bitmap_pkt = NULL;
|
|
|
|
upgrade_info = &p_sg_glb->desc.sta->upgrade_info;
|
|
|
|
iot_sg_printf("sg_upgrade: %s, local_id = %x id = %X start_seq = %d,"
|
|
"cnt = %d\n", __FUNCTION__, upgrade_info->upgrade_id, id, start_seq,
|
|
cnt);
|
|
|
|
bitmap_pkt = iot_sg_sta_get_recv_bitmap(start_seq, cnt);
|
|
if (bitmap_pkt == NULL) {
|
|
return;
|
|
}
|
|
|
|
if (IOT_SG_STA_QUERY_ALL_BLOCK == cnt) {
|
|
cnt = (uint16_t)upgrade_info->block_cnt;
|
|
}
|
|
|
|
iot_sg_sta_send_query_reply(upgrade_info->upgrade_id, start_seq,
|
|
upgrade_info->state, cnt, bitmap_pkt, IOT_PLC_MSG_TYPE_UNICAST,
|
|
session_type);
|
|
}
|
|
|
|
void iot_sg_sta_handle_upgrade_execute(uint32_t id, uint16_t reset_delay,
|
|
uint32_t trial_run_dur, uint8_t rsp_flag)
|
|
{
|
|
uint32_t result = 0;
|
|
|
|
iot_sg_sta_upgrade_info_t *upgrade_info = NULL;
|
|
upgrade_info = &p_sg_glb->desc.sta->upgrade_info;
|
|
if (upgrade_info->state != IOT_SG_STA_UPGRADE_ST_RECEIVE &&
|
|
upgrade_info->state != IOT_SG_STA_UPGRADE_ST_RECV_DONE) {
|
|
result = IOT_PLC_UPGRADE_OK;
|
|
goto exit_label;
|
|
}
|
|
|
|
if ((!upgrade_info->skip) && (!iot_sg_sta_recv_all_block())) {
|
|
result = IOT_PLC_UPGRADE_ERR_UNKNOWN;
|
|
goto exit_label;
|
|
}
|
|
|
|
if (id == upgrade_info->upgrade_id) {
|
|
if (upgrade_info->ext_dev_need_upgrade_flag) {
|
|
iot_sg_sta_ext_upgrade_pre_process();
|
|
} else {
|
|
upgrade_info->reset_wait_dur = reset_delay;
|
|
upgrade_info->trail_run_dur = trial_run_dur;
|
|
iot_sg_sta_start_upgrade_timer(upgrade_info->reset_wait_dur * 1000);
|
|
}
|
|
iot_dbglog_input(IOT_SMART_GRID_MID, DBGLOG_ERR,
|
|
IOT_SG_STA_UPGRADE_DBG_ID, 2, 5, upgrade_info->state);
|
|
iot_sg_sta_upgrade_goto_state(IOT_SG_STA_UPGRADE_ST_EXECUTE);
|
|
}
|
|
exit_label:
|
|
if ((upgrade_info->session_type == IOT_SG_STA_UPGRADE_SESSION_TYPE_NW) &&
|
|
rsp_flag) {
|
|
iot_sg_sta_nw_send_exe_ack(id, IOT_PLC_MSG_TYPE_UNICAST, result);
|
|
}
|
|
iot_sg_printf("sg_upgrade: %s, result: %d\n", __FUNCTION__, result);
|
|
}
|
|
|
|
void iot_sg_sta_handle_stop_upgrade(uint32_t id, uint8_t rsp_flag)
|
|
{
|
|
iot_sg_sta_upgrade_info_t *upgrade_info = NULL;
|
|
|
|
upgrade_info = &p_sg_glb->desc.sta->upgrade_info;
|
|
iot_sg_printf("sg_upgrade: %s. stop_upgrade_id = %08X. state = %d\n",
|
|
__FUNCTION__, id, upgrade_info->state);
|
|
|
|
if ((upgrade_info->state >= IOT_SG_STA_UPGRADE_ST_RECEIVE) &&
|
|
(!upgrade_info->skip)) {
|
|
iot_sg_sta_renew_exit_reason_code(IOT_SG_STA_UPGRADE_EXIT_STOP_CMD);
|
|
}
|
|
|
|
if (upgrade_info->state == IOT_SG_STA_UPGRADE_ST_TRAIL_RUN) {
|
|
/* switch back to previous image */
|
|
iot_sg_printf("sg_upgrade: %s. switch back for stop_upgrade\n");
|
|
iot_upgrade_switch_part();
|
|
iot_upgrade_reset();
|
|
} else {
|
|
iot_sg_sta_upgrade_clear(id, 1);
|
|
}
|
|
|
|
if ((upgrade_info->session_type == IOT_SG_STA_UPGRADE_SESSION_TYPE_NW) &&
|
|
rsp_flag) {
|
|
iot_sg_sta_nw_send_stop_ack(id, IOT_PLC_UPGRADE_OK);
|
|
}
|
|
}
|
|
|
|
void iot_sg_sta_upgrade_on_join(uint32_t new_nw_joined)
|
|
{
|
|
iot_sg_sta_upgrade_info_t *p_info = &p_sg_glb->desc.sta->upgrade_info;
|
|
|
|
if (new_nw_joined) {
|
|
/* STA just joined a new network or CCo rebooted,
|
|
* stop current upgrading session if necessary.
|
|
*/
|
|
if ((IOT_SG_STA_UPGRADE_ST_RECEIVE == p_info->state) || p_info->skip) {
|
|
if (!p_info->skip) {
|
|
iot_sg_sta_renew_exit_reason_code(
|
|
IOT_SG_STA_UPGRADE_EXIT_NID_CHANGE);
|
|
}
|
|
iot_sg_sta_upgrade_clear(p_info->upgrade_id, 1);
|
|
}
|
|
}
|
|
|
|
if ((p_info->state > IOT_SG_STA_UPGRADE_ST_IDLE) &&
|
|
(p_info->state < IOT_SG_STA_UPGRADE_ST_TRAIL_RUN)) {
|
|
iot_plc_led_request(IOT_PLC_LED_UPGRADE_ON);
|
|
}
|
|
}
|
|
|
|
void iot_sg_sta_upgrade_on_leave()
|
|
{
|
|
iot_sg_sta_upgrade_info_t *p_info = &p_sg_glb->desc.sta->upgrade_info;
|
|
if (!p_info->skip) {
|
|
if (iot_sg_sta_recv_all_block()) {
|
|
if (p_info->ext_dev_need_upgrade_flag) {
|
|
iot_sg_sta_ext_upgrade_pre_process();
|
|
goto exit_label;
|
|
} else {
|
|
/* if STA received new FW, switch to new FW when leave network. */
|
|
if (p_info->trail_run_dur == 0) {
|
|
p_info->trail_run_dur = IOT_SG_STA_DEFAULT_TRAIL_RUN_DUR;
|
|
}
|
|
|
|
iot_sg_printf("sg upgrade: reset on sta leave."
|
|
"st = %d, trail = %d\n", p_info->state, p_info->trail_run_dur);
|
|
iot_dbglog_input(IOT_SMART_GRID_MID, DBGLOG_ERR,
|
|
IOT_SG_STA_UPGRADE_DBG_ID, 2, 6, p_info->state);
|
|
|
|
iot_sg_sta_save_to_flash();
|
|
iot_pkg_upgrade_commit(p_info->upgrade_id);
|
|
iot_pkg_upgrade_reset();
|
|
goto exit_label;
|
|
}
|
|
}
|
|
|
|
if (p_info->state == IOT_SG_STA_UPGRADE_ST_EXECUTE) {
|
|
/* leave network before execute delay timeout.
|
|
* reset to use the new firmware image.
|
|
*/
|
|
iot_sg_printf("sg upgrade: reset on sta leave."
|
|
"st = %d, trail = %d\n", p_info->state, p_info->trail_run_dur);
|
|
iot_dbglog_input(IOT_SMART_GRID_MID, DBGLOG_ERR,
|
|
IOT_SG_STA_UPGRADE_DBG_ID, 2, 7, p_info->state);
|
|
iot_pkg_upgrade_reset();
|
|
goto exit_label;
|
|
}
|
|
}
|
|
|
|
if ((p_info->state > IOT_SG_STA_UPGRADE_ST_IDLE) &&
|
|
(p_info->state < IOT_SG_STA_UPGRADE_ST_TRAIL_RUN)) {
|
|
iot_plc_led_request(IOT_PLC_LED_UPGRADE_OFF);
|
|
}
|
|
|
|
if (p_info->state != IOT_SG_STA_UPGRADE_ST_INVALID &&
|
|
p_info->state != IOT_SG_STA_UPGRADE_ST_IDLE) {
|
|
iot_dbglog_input(IOT_SMART_GRID_MID, DBGLOG_ERR,
|
|
IOT_SG_STA_UPGRADE_DBG_ID, 2, 8, p_info->state);
|
|
}
|
|
exit_label:
|
|
return;
|
|
}
|
|
|
|
uint32_t iot_sg_sta_upgrade_handle_file_segment(uint8_t action,
|
|
uint8_t session_type, uint16_t seg_index, uint16_t total_seg_cnt,
|
|
uint8_t *seg_data, uint16_t seg_len, uint8_t allow_skip, uint16_t window)
|
|
{
|
|
uint32_t ret = ERR_OK, file_crc, file_size, result;
|
|
iot_sg_sta_upgrade_info_t *upgrade_info = &p_sg_glb->desc.sta->upgrade_info;
|
|
iot_pkt_t *src_pkt = NULL;
|
|
|
|
switch (action) {
|
|
case IOT_SG_STA_SEG_UPGRADE_ACTION_STOP:
|
|
{
|
|
iot_sg_sta_handle_stop_upgrade(0, 0);
|
|
break;
|
|
}
|
|
case IOT_SG_STA_SEG_UPGRADE_ACTION_UPGRADE:
|
|
{
|
|
if (total_seg_cnt == 0 || seg_len == 0 || !seg_data) {
|
|
/* reject invalid data packet. */
|
|
ret = ERR_FAIL;
|
|
goto out;
|
|
}
|
|
if (0 == seg_index) {
|
|
/* support new session type restart upgrade */
|
|
if ((IOT_SG_STA_UPGRADE_SESSION_TYPE_INVALID !=
|
|
upgrade_info->session_type) &&
|
|
(session_type != upgrade_info->session_type)) {
|
|
iot_sg_sta_handle_stop_upgrade(0, 0);
|
|
}
|
|
if (IOT_FILE_TYPE_INVALID == iot_get_file_type(seg_data)) {
|
|
/* reject invalid data packet. */
|
|
if (allow_skip) {
|
|
upgrade_info->skip = 1;
|
|
upgrade_info->session_type = session_type;
|
|
} else {
|
|
ret = ERR_FAIL;
|
|
}
|
|
iot_sg_printf("%s invalid upgrade file\n", __FUNCTION__);
|
|
goto out;
|
|
}
|
|
if (iot_get_vendor_id(seg_data) != iot_sg_get_vendor_id()) {
|
|
/* reject invalid data packet. */
|
|
if (allow_skip) {
|
|
upgrade_info->skip = 1;
|
|
upgrade_info->session_type = session_type;
|
|
} else {
|
|
ret = ERR_FAIL;
|
|
}
|
|
iot_sg_printf("%s invalid vendor id\n", __FUNCTION__);
|
|
goto out;
|
|
}
|
|
|
|
file_size = iot_get_file_len(seg_data) +
|
|
iot_get_file_header_len(seg_data);
|
|
file_crc = iot_get_file_crc(seg_data);
|
|
|
|
if (IOT_SG_STA_UPGRADE_ST_IDLE == upgrade_info->state) {
|
|
/* get a new upgrade id if it's 0. */
|
|
upgrade_info->upgrade_id++;
|
|
if (upgrade_info->upgrade_id == 0) {
|
|
upgrade_info->upgrade_id = 1;
|
|
}
|
|
}
|
|
|
|
result = iot_sg_sta_handle_start_upgrade(upgrade_info->upgrade_id,
|
|
window, seg_len, file_size, total_seg_cnt, file_crc, 0,
|
|
session_type);
|
|
if ((IOT_PLC_UPGRADE_OK != result) &&
|
|
(IOT_PLC_UPGRADE_ERR_SAME_VERSION != result)) {
|
|
ret = ERR_FAIL;
|
|
goto out;
|
|
}
|
|
}
|
|
if (session_type != upgrade_info->session_type) {
|
|
ret = ERR_FAIL;
|
|
goto out;
|
|
}
|
|
if (upgrade_info->skip) {
|
|
if (!allow_skip) {
|
|
ret = ERR_FAIL;
|
|
}
|
|
goto out;
|
|
}
|
|
src_pkt = iot_pkt_alloc(seg_len, IOT_SMART_GRID_MID);
|
|
if (NULL == src_pkt) {
|
|
ret = ERR_FAIL;
|
|
goto out;
|
|
}
|
|
os_mem_cpy(iot_pkt_put(src_pkt, seg_len), seg_data, seg_len);
|
|
iot_sg_sta_handle_upgrade_data(upgrade_info->upgrade_id,
|
|
seg_len, seg_index, iot_pkt_data(src_pkt), src_pkt, 0);
|
|
break;
|
|
}
|
|
default:
|
|
ret = ERR_FAIL;
|
|
break;
|
|
}
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
#endif /* IOT_SMART_GRID_ENABLE */
|