#include "sdkconfig.h" #include #include "cli.h" #include #include "driver/flash.h" #include "modules/ota.h" #if CONFIG_OTA_HTTP #include "utils_httpc.h" #include "modules/wifi.h" #endif #ifdef CONFIG_OTA_HASH_FUNCTION #include "vendor_flash_partition.h" #endif #include "common/bk_err.h" #include "bk_private/bk_ota_private.h" #ifndef OTA_TAG #define OTA_TAG "OTA" #endif #ifdef CONFIG_OTA_DEBUG_LOG_OPEN #define OTA_LOGI(...) BK_LOGI(OTA_TAG, ##__VA_ARGS__) #define OTA_LOGW(...) BK_LOGW(OTA_TAG, ##__VA_ARGS__) #define OTA_LOGE(...) BK_LOGE(OTA_TAG, ##__VA_ARGS__) #define OTA_LOGD(...) BK_LOGD(OTA_TAG, ##__VA_ARGS__) #else #define OTA_LOGI(...) BK_LOGI(OTA_TAG, ##__VA_ARGS__) #define OTA_LOGW(...) #define OTA_LOGE(...) BK_LOGE(OTA_TAG, ##__VA_ARGS__) #define OTA_LOGD(...) #endif #define FLASH_DEFAULT_VALUE (0xFFFFFFFF) #ifdef CONFIG_HTTP_AB_PARTITION #define OTA_DEBUG_TEST (0) #define FLASH_BASE_ADDRESS (0x44030000) #define FLASH_OFFSET_ENABLE (0x19) #define OTA_FINA_EXEC_FLAG_OFFSET (0x0) #define OTA_TEMP_EXEC_FLAG_OFFSET (0x4) #define OTA_CUSTM_CONF_FLAG_OFFSET (0x8) #define OTA_DOWNLOAD_STATUS_FLAG_OFFSET (0xC) //0xFE.download start. //0xFC download success part_flag update_part_flag; #if CONFIG_OTA_POSITION_INDEPENDENT_AB static uint8 ota_get_flash_offset_enable_value(void) { uint8 ret_val; ret_val = (REG_READ((FLASH_BASE_ADDRESS + FLASH_OFFSET_ENABLE*4)) & 0x1); OTA_LOGI("ret_val :0x%x\r\n",ret_val); return ret_val; } void bk_ota_double_check_for_execution(void) { uint8 ret; ret = bk_ota_get_current_partition(); if(ret == 0) { OTA_LOGI("confirm exec pos_ind part a \r\n"); bk_ota_confirm_update_partition(CONFIRM_EXEC_A); } else { OTA_LOGI("confirm exec pos_ind part b \r\n"); bk_ota_confirm_update_partition(CONFIRM_EXEC_B); } } #endif uint8 bk_ota_get_current_partition(void) { #if CONFIG_OTA_POSITION_INDEPENDENT_AB uint8 ret_val; ret_val = ota_get_flash_offset_enable_value(); return ret_val; //ret_val: 0x0 represents A 0x1 :represents B. #else exec_flag ota_exec_flag = 5; bk_logic_partition_t *bk_ptr = NULL; bk_ptr = bk_flash_partition_get_info(BK_PARTITION_OTA_FINA_EXECUTIVE); OTA_LOGI("bk_ptr->partition_start_addr :0x%x\r\n",bk_ptr->partition_start_addr); bk_flash_read_bytes(bk_ptr->partition_start_addr ,(uint8_t *)&ota_exec_flag, sizeof(u8)); return ota_exec_flag ; // ota_exec_flag :0x0/0xFF represents A 0x1 :represents B #endif } void ota_write_flash(bk_partition_t ota_partition_flag, u8 flag, u8 offset) { bk_logic_partition_t *bk_ptr = NULL; u8 ota_final_buff[1],ota_temp_buff[1],ota_cconfirm_buff[1],ota_download_status_buff[1]; #if OTA_DEBUG_TEST u8 temp1_buff[1],temp2_buff[1],temp3_buff[1],temp4_buff[1]; #endif flash_protect_type_t protect_type; bk_ptr = bk_flash_partition_get_info(ota_partition_flag); OTA_LOGD("ota_write_flash:partition_start_addr:0x%x\r\n",(bk_ptr->partition_start_addr)); bk_flash_read_bytes((bk_ptr->partition_start_addr),(uint8_t *)ota_final_buff, sizeof(u8)); bk_flash_read_bytes((bk_ptr->partition_start_addr + OTA_TEMP_EXEC_FLAG_OFFSET),(uint8_t *)ota_temp_buff, sizeof(u8)); bk_flash_read_bytes((bk_ptr->partition_start_addr + OTA_CUSTM_CONF_FLAG_OFFSET),(uint8_t *)ota_cconfirm_buff, sizeof(u8)); bk_flash_read_bytes((bk_ptr->partition_start_addr + OTA_DOWNLOAD_STATUS_FLAG_OFFSET),(uint8_t *)ota_download_status_buff, sizeof(u8)); OTA_LOGD("before:ota_final_buff:0x%x,ota_temp_buff:0x%x,ota_cconfirm_buff:0x%x\r\n", ota_final_buff[0],ota_temp_buff[0],ota_cconfirm_buff[0]); protect_type = bk_flash_get_protect_type(); bk_flash_set_protect_type(FLASH_PROTECT_NONE); bk_flash_erase_sector(bk_ptr->partition_start_addr); if(offset == OTA_FINA_EXEC_FLAG_OFFSET) { OTA_LOGD("offset == 0\r\n"); bk_flash_write_bytes((bk_ptr->partition_start_addr + offset),(uint8_t *)&flag, sizeof(u8)); bk_flash_write_bytes((bk_ptr->partition_start_addr + OTA_TEMP_EXEC_FLAG_OFFSET),(uint8_t *)ota_temp_buff, sizeof(u8)); bk_flash_write_bytes((bk_ptr->partition_start_addr + OTA_CUSTM_CONF_FLAG_OFFSET),(uint8_t *)ota_cconfirm_buff, sizeof(u8)); bk_flash_write_bytes((bk_ptr->partition_start_addr + OTA_DOWNLOAD_STATUS_FLAG_OFFSET),(uint8_t *)ota_download_status_buff, sizeof(u8)); } else if(offset == OTA_TEMP_EXEC_FLAG_OFFSET) { OTA_LOGD("offset == 4\r\n"); bk_flash_write_bytes((bk_ptr->partition_start_addr),(uint8_t *)ota_final_buff, sizeof(u8)); bk_flash_write_bytes((bk_ptr->partition_start_addr + offset),(uint8_t *)&flag, sizeof(u8)); bk_flash_write_bytes((bk_ptr->partition_start_addr + OTA_CUSTM_CONF_FLAG_OFFSET),(uint8_t *)ota_cconfirm_buff, sizeof(u8)); bk_flash_write_bytes((bk_ptr->partition_start_addr + OTA_DOWNLOAD_STATUS_FLAG_OFFSET),(uint8_t *)ota_download_status_buff, sizeof(u8)); } else if(offset == OTA_CUSTM_CONF_FLAG_OFFSET) { OTA_LOGD("offset == 8\r\n"); bk_flash_write_bytes((bk_ptr->partition_start_addr),(uint8_t *)ota_final_buff, sizeof(u8)); bk_flash_write_bytes((bk_ptr->partition_start_addr + OTA_TEMP_EXEC_FLAG_OFFSET),(uint8_t *)ota_temp_buff,sizeof(u8)); bk_flash_write_bytes((bk_ptr->partition_start_addr + offset),(uint8_t *)&flag, sizeof(u8)); bk_flash_write_bytes((bk_ptr->partition_start_addr + OTA_DOWNLOAD_STATUS_FLAG_OFFSET),(uint8_t *)ota_download_status_buff, sizeof(u8)); } else if(offset == OTA_DOWNLOAD_STATUS_FLAG_OFFSET) { OTA_LOGD("offset ==12\r\n"); bk_flash_write_bytes((bk_ptr->partition_start_addr),(uint8_t *)ota_final_buff, sizeof(u8)); bk_flash_write_bytes((bk_ptr->partition_start_addr + OTA_TEMP_EXEC_FLAG_OFFSET),(uint8_t *)ota_temp_buff,sizeof(u8)); bk_flash_write_bytes((bk_ptr->partition_start_addr + OTA_CUSTM_CONF_FLAG_OFFSET),(uint8_t *)ota_cconfirm_buff, sizeof(u8)); bk_flash_write_bytes((bk_ptr->partition_start_addr + offset),(uint8_t *)&flag, sizeof(u8)); } else { OTA_LOGE("input offset value is error !!!! \r\n"); } #if OTA_DEBUG_TEST bk_flash_read_bytes((bk_ptr->partition_start_addr + OTA_FINA_EXEC_FLAG_OFFSET),(uint8_t *)temp1_buff, sizeof(u8)); bk_flash_read_bytes((bk_ptr->partition_start_addr + OTA_TEMP_EXEC_FLAG_OFFSET),(uint8_t *)temp2_buff, sizeof(u8)); bk_flash_read_bytes((bk_ptr->partition_start_addr + OTA_CUSTM_CONF_FLAG_OFFSET),(uint8_t *)temp3_buff, sizeof(u8)); bk_flash_read_bytes((bk_ptr->partition_start_addr + OTA_DOWNLOAD_STATUS_FLAG_OFFSET),(uint8_t *)temp4_buff, sizeof(u8)); OTA_LOGD("ota_final_buff:0x%x,ota_temp_buff:0x%x,ota_cconfirm_buff:0x%x,ota_download_status_buff:0x%x\r\n", temp1_buff[0],temp2_buff[0],temp3_buff[0],temp4_buff[0]); #endif bk_flash_set_protect_type(protect_type); } void bk_ota_confirm_update_partition(ota_confirm_flag ota_confirm_val) { exec_flag ota_exec_flag ; uint8 last_exec_flag; bk_logic_partition_t *bk_ptr = NULL; bk_ptr = bk_flash_partition_get_info(BK_PARTITION_OTA_FINA_EXECUTIVE); bk_flash_read_bytes((bk_ptr->partition_start_addr + 8) ,(uint8_t *)&last_exec_flag, sizeof(u8)); OTA_LOGI("bk_ptr->partition_start_addr:0x%x,last_exec_flag:0x%x\r\n",bk_ptr->partition_start_addr,last_exec_flag); if(last_exec_flag != ota_confirm_val) { ota_write_flash(BK_PARTITION_OTA_FINA_EXECUTIVE, ota_confirm_val,8); if(ota_confirm_val == CONFIRM_EXEC_A) { ota_exec_flag = EXEX_A_PART; ota_write_flash(BK_PARTITION_OTA_FINA_EXECUTIVE, ota_exec_flag, 0); } else if(ota_confirm_val == CONFIRM_EXEC_B) { ota_exec_flag = EXEC_B_PART; ota_write_flash(BK_PARTITION_OTA_FINA_EXECUTIVE, ota_exec_flag, 0); } } } static callback_func update_state_cb = NULL; void bk_ota_register_temp_partition_callback(callback_func cb) { update_state_cb = cb; } uint8_t ota_temp_execute_partition(int state_val) { uint8_t temp_exec_flag = 6; if(update_state_cb) { temp_exec_flag = update_state_cb(state_val); } return temp_exec_flag; } #ifdef CONFIG_OTA_HASH_FUNCTION int32_t ota_do_hash_check(void) { struct ota_rbl_head rbl_hdr; const bk_logic_partition_t *bk_ptr = NULL; uint32_t partition_length = 0; int ret = BK_FAIL; if(update_part_flag == UPDATE_B_PART) { bk_ptr = bk_flash_partition_get_info(BK_PARTITION_S_APP_USER); //note: when update_partition is B, arg: BK_PARTITION_APPLICATION1,update_partition is A??arg: BK_PARTITION_APPLICATION } else{ //B-->A bk_ptr = bk_flash_partition_get_info(BK_PARTITION_APPLICATION); } partition_length = bk_flash_partition_get_info(BK_PARTITION_S_APP_USER)->partition_length; OTA_LOGD("partition_length :0x%x",partition_length); if((bk_ptr == NULL)) { OTA_LOGE(" get %s fail \r\n",bk_ptr->partition_owner); return BK_FAIL; } ota_get_rbl_head(bk_ptr, &rbl_hdr, partition_length); ret = ota_hash_verify(bk_ptr, &rbl_hdr); if(ret == BK_OK) { OTA_LOGI("hash sucess!!!! \r\n"); } return ret; } #endif void ota_write_flash_with_all_flag(bk_partition_t ota_partition_flag, uint8_t *p_flag_buf, uint8_t offset, uint8_t size) { bk_logic_partition_t *bk_ptr = NULL; flash_protect_type_t protect_type; bk_ptr = bk_flash_partition_get_info(ota_partition_flag); protect_type = bk_flash_get_protect_type(); bk_flash_set_protect_type(FLASH_PROTECT_NONE); bk_flash_erase_sector(bk_ptr->partition_start_addr + offset); bk_flash_write_bytes((bk_ptr->partition_start_addr + offset), (uint8_t *)p_flag_buf, size); bk_flash_set_protect_type(protect_type); } int bk_ota_update_partition_flag(int input_val) { uint8_t cust_confirm_flag; exec_flag ota_exec_flag; exec_flag exec_temp_part; ota_temp_exec_flag temp_exec_flag ; if(update_part_flag == UPDATE_B_PART){ ota_exec_flag = EXEC_B_PART; }else{ ota_exec_flag = EXEX_A_PART; } #ifdef CONFIG_OTA_UPDATE_DEFAULT_PARTITION #if CONFIG_OTA_POSITION_INDEPENDENT_AB if(update_part_flag == UPDATE_A_PART){ temp_exec_flag = CONFIRM_EXEC_A; //update A Partition; }else{ temp_exec_flag = CONFIRM_EXEC_B; //update B Partition; } #else #ifdef CONFIG_OTA_UPDATE_B_PARTITION temp_exec_flag = CONFIRM_EXEC_B; //update B Partition; #else temp_exec_flag = CONFIRM_EXEC_A; //update A Partition; #endif #endif #else temp_exec_flag = ota_temp_execute_partition(input_val); //temp_exec_flag :3 :A ,4:B #endif OTA_LOGD("from cus temp_exec_flag:0x%x \r\n",temp_exec_flag); if(temp_exec_flag == CONFIRM_EXEC_A){ OTA_LOGI("B>>A \r\n"); exec_temp_part = EXEX_A_PART; }else if(temp_exec_flag == CONFIRM_EXEC_B){ OTA_LOGI("A>>B \r\n"); exec_temp_part = EXEC_B_PART; }else{ OTA_LOGE("temp_exec_flag is error \r\n"); return BK_FAIL; } cust_confirm_flag= 0x1; //represent do ota update. #if CONFIG_OTA_EVADE_METHOD uint8_t download_status_flag = DOWNLOAD_SUCCESS_FLAG; #endif OTA_LOGI("ota_exec_flag :0x%x, exec_temp_part :0x%x,cust_confirm_flag :0x%x ,download_status_flag :0x%x\r\n",\ ota_exec_flag ,exec_temp_part, cust_confirm_flag,download_status_flag); uint8_t input_flag_buf[16]= {0}; //{ota_exec_flag,0xFF,0xFF,0xFF,exec_temp_part,0xFF,0xFF,0xFF,cust_confirm_flag,0,0,0,download_status_flag,0,0,0}; os_memset(&input_flag_buf[0], 0xFF, sizeof(input_flag_buf)); os_memcpy(&input_flag_buf[0], &ota_exec_flag, 1); os_memcpy(&input_flag_buf[4], &exec_temp_part, 1); os_memcpy(&input_flag_buf[8], &cust_confirm_flag, 1); os_memcpy(&input_flag_buf[12], &download_status_flag, 1); ota_write_flash_with_all_flag(BK_PARTITION_OTA_FINA_EXECUTIVE, input_flag_buf, 0, 16); return BK_OK; } int bk_ota_swap_execute_partition(void) { uint8_t ota_flag_buf[16]= {0}; uint32_t a_app_head= 0; uint32_t b_app_head= 0; bk_logic_partition_t *bk_ota_ptr = NULL; bk_logic_partition_t *a_app_ptr = NULL; bk_logic_partition_t *b_app_ptr = NULL; a_app_ptr = bk_flash_partition_get_info(BK_PARTITION_APPLICATION); b_app_ptr = bk_flash_partition_get_info(BK_PARTITION_S_APP_USER); bk_ota_ptr = bk_flash_partition_get_info(BK_PARTITION_OTA_FINA_EXECUTIVE); if((bk_ota_ptr == NULL)||(a_app_ptr == NULL) ||(b_app_ptr == NULL)) { os_printf("get partition fail! \r\n"); return BK_FAIL; } bk_flash_read_bytes((a_app_ptr->partition_start_addr), (uint8_t *)&a_app_head, sizeof(uint32_t)); bk_flash_read_bytes((b_app_ptr->partition_start_addr), (uint8_t *)&b_app_head, sizeof(uint32_t)); //os_printf("a_app_head :0x%x ,b_app_head :0x%x \r\n", a_app_head, b_app_head); if ((a_app_head == FLASH_DEFAULT_VALUE)||(b_app_head == FLASH_DEFAULT_VALUE)) { os_printf("only one execute partition and forbid swap! \r\n"); return BK_FAIL; } else { flash_protect_type_t protect_type = bk_flash_get_protect_type(); bk_flash_set_protect_type(FLASH_PROTECT_NONE); exec_flag ret = bk_ota_get_current_partition(); if(ret == EXEX_A_PART) //execute A { os_printf("execute A, swap to B \r\n"); bk_flash_erase_sector(bk_ota_ptr->partition_start_addr); exec_flag ota_exec_flag = EXEC_B_PART; os_memset(&ota_flag_buf[0], 0xFF, sizeof(ota_flag_buf)); os_memcpy(&ota_flag_buf[0], &ota_exec_flag, 1); bk_flash_write_bytes(bk_ota_ptr->partition_start_addr, ota_flag_buf, sizeof(ota_flag_buf)); } else if(ret == EXEC_B_PART) //execute B { os_printf("execute B, swap to A \r\n"); bk_flash_erase_sector(bk_ota_ptr->partition_start_addr); } else { os_printf("swap partition fail! \r\n"); } bk_flash_set_protect_type(protect_type); return BK_OK; } } #if CONFIG_OTA_DISPLAY_PICTURE_DEMO int ota_update_with_display_open(void) { int ret = BK_OK; lvgl_app_deinit(); audio_turn_off(); if(media_app_ota_disp_open() != BK_OK) { os_printf("open disp failed. \r\n"); ret = BK_FAIL; } return ret; } #endif #endif // CONFIG_HTTP_AB_PARTITION static ota_event_callback_t s_ota_event_callback = NULL; int ota_event_callback_register(ota_event_callback_t callback) { s_ota_event_callback = callback; return 0; } int ota_input_event_handler(evt_ota event_param) { if(NULL != s_ota_event_callback) { s_ota_event_callback(event_param); } return 0; } u8 ota_flag =0; #if CONFIG_OTA_HTTP int bk_http_ota_download(const char *uri) { int ret; httpclient_t httpclient; httpclient_data_t httpclient_data; char http_content[HTTP_RESP_CONTENT_LEN]; if(!uri){ ret = BK_FAIL; OTA_LOGE( "uri is NULL\r\n"); return ret; } OTA_LOGD("http_ota_download :0x%x",bk_http_ota_download); #if CONFIG_OTA_DISPLAY_PICTURE_DEMO if(ota_update_with_display_open() != BK_OK) { return BK_FAIL; } #endif ota_input_event_handler(EVT_OTA_START); #ifdef CONFIG_HTTP_AB_PARTITION ret = bk_ota_get_current_partition(); OTA_LOGI("ret :0x%x \r\n",ret); if(ret == EXEC_B_PART){ update_part_flag = UPDATE_A_PART; } else{ update_part_flag = UPDATE_B_PART; } #endif #if CONFIG_SYSTEM_CTRL bk_wifi_ota_dtim(1); #endif ota_flag = 1; os_memset(&httpclient, 0, sizeof(httpclient_t)); os_memset(&httpclient_data, 0, sizeof(httpclient_data)); os_memset(&http_content, 0, sizeof(HTTP_RESP_CONTENT_LEN)); httpclient.header = "Accept: text/xml,text/html,\r\n"; httpclient_data.response_buf = http_content; httpclient_data.response_content_len = HTTP_RESP_CONTENT_LEN; ret = httpclient_common(&httpclient, uri, 80,/*port*/ NULL, HTTPCLIENT_GET, 180000, &httpclient_data); ota_flag = 0; if (0 != ret){ OTA_LOGE("request epoch time from remote server failed.ret:%d\r\n",ret); ota_input_event_handler(EVT_OTA_FAIL); #if CONFIG_OTA_DISPLAY_PICTURE_DEMO if(media_app_ota_disp_close() != BK_OK) { OTA_LOGE("disp close failed.ret:%d\r\n",ret); return BK_FAIL; } #endif #if CONFIG_SYSTEM_CTRL bk_wifi_ota_dtim(0); #endif }else{ #ifdef CONFIG_HTTP_AB_PARTITION int ret_val = 0; #ifdef CONFIG_OTA_HASH_FUNCTION ret_val= ota_do_hash_check(); if(ret_val != BK_OK) { OTA_LOGE("hash fail.\r\n"); return ret_val; } #endif ret_val = bk_ota_update_partition_flag(ret); if(ret_val != BK_OK) { return ret_val; } ota_input_event_handler(EVT_OTA_SUCCESS); #if CONFIG_OTA_DISPLAY_PICTURE_DEMO if(media_app_ota_disp_close() != BK_OK) { OTA_LOGE("disp close failed.ret:%d\r\n",ret); } #endif OTA_LOGI("success.\r\n"); bk_reboot(); #else OTA_LOGI("success.\r\n"); bk_reboot(); #endif /*CONFIG_HTTP_AB_PARTITION*/ } return ret; } #endif