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