static ota_status_t ota_verify_image_crc32(image_seq_t seq, uint32_t *value) { CE_CRC_Handler hdl; uint32_t crc; if (HAL_CRC_Init(&hdl, CE_CRC32, ota_priv.get_size) != HAL_OK) { OTA_ERR("CRC init failed\n"); return OTA_STATUS_ERROR; } if (ota_verify_image_append(seq, (ota_verify_append_t)HAL_CRC_Append, (void *)&hdl) != OTA_STATUS_OK) { OTA_ERR("CRC append failed\n"); return OTA_STATUS_ERROR; } if (HAL_CRC_Finish(&hdl, &crc) != HAL_OK) { OTA_ERR("CRC finish failed\n"); return OTA_STATUS_ERROR; } OTA_DBG("%s(), value %#x, crc %#x\n", __func__, *value, crc); if (ota_memcmp(value, &crc, sizeof(crc)) == 0) { return OTA_STATUS_OK; } else { return OTA_STATUS_ERROR; } }
static ota_status_t ota_verify_image_sha256(image_seq_t seq, uint32_t *value) { CE_SHA256_Handler hdl; uint32_t digest[8]; if (HAL_SHA256_Init(&hdl, CE_CTL_IVMODE_SHA_MD5_FIPS180, NULL) != HAL_OK) { OTA_ERR("SHA256 init failed\n"); return OTA_STATUS_ERROR; } if (ota_verify_image_append(seq, (ota_verify_append_t)HAL_SHA256_Append, (void *)&hdl) != OTA_STATUS_OK) { OTA_ERR("SHA256 append failed\n"); return OTA_STATUS_ERROR; } if (HAL_SHA256_Finish(&hdl, digest) != HAL_OK) { OTA_ERR("SHA256 finish failed\n"); return OTA_STATUS_ERROR; } OTA_DBG("%s(), value[0] %#x, digest[0] %#x\n", __func__, value[0], digest[0]); if (ota_memcmp(value, digest, sizeof(digest)) == 0) { return OTA_STATUS_OK; } else { return OTA_STATUS_ERROR; } }
static ota_status_t ota_verify_image_append(image_seq_t seq, ota_verify_append_t append, void *hdl) { ota_priv_t *ota = &ota_priv; const image_ota_param_t *iop = ota->iop; OTA_DBG("%s(), seq %d\n", __func__, seq); if (ota_verify_image_append_process(IMG_BL_FLASH(iop), IMG_BL_ADDR(iop), iop->bl_size, append, hdl) != OTA_STATUS_OK) { OTA_ERR("append bl fail, seq %d\n", seq); return OTA_STATUS_ERROR; } if (ota_verify_image_append_process(iop->flash[seq], iop->addr[seq], ota->get_size - iop->bl_size, append, hdl) != OTA_STATUS_OK) { OTA_ERR("append image fail, seq %d\n", seq); return OTA_STATUS_ERROR; } return OTA_STATUS_OK; }
static void pmt_request(handle_t handle, u32 param) { ts_ota_priv_data_t *p_this = (ts_ota_priv_data_t *)handle; dvb_request_t dvb_req = {0}; dvb_req.req_mode = DATA_SINGLE; dvb_req.period = 0; dvb_req.table_id = DVB_TABLE_ID_PMT; dvb_req.para1 = DVB_TABLE_ID_PMT; dvb_req.para2 = param; dvb_req.context = param; p_this->p_svc->do_cmd(p_this->p_svc, DVB_REQUEST, (u32)&dvb_req, sizeof(dvb_request_t)); OTA_DBG(("ts ota: pmt request\n")); }
static void sdt_request(handle_t handle, u32 sec_index) { ts_ota_priv_data_t *p_this = (ts_ota_priv_data_t *)handle; dvb_request_t dvb_req = {0}; dvb_req.req_mode = DATA_SINGLE; dvb_req.period = 0; dvb_req.table_id = DVB_TABLE_ID_SDT_ACTUAL; dvb_req.para1 = DVB_TABLE_ID_SDT_ACTUAL; dvb_req.para2 = sec_index; dvb_req.context = 0; p_this->p_svc->do_cmd(p_this->p_svc, DVB_REQUEST, (u32)&dvb_req, sizeof(dvb_request_t)); OTA_DBG(("ts ota: sdt request\n")); }
/** * @brief Get the image sequence which to be updated by OTA * @return Image sequence to be updated */ static image_seq_t ota_get_update_seq(void) { image_seq_t seq = IMAGE_SEQ_NUM; const image_ota_param_t *iop = ota_priv.iop; if (iop == NULL) { OTA_ERR("not init"); return seq; } if ((iop->img_max_size == 0) || (iop->bl_size == 0) || (iop->running_seq >= IMAGE_SEQ_NUM)) { OTA_ERR("not init, img_max_size %#x, bl_size %#x, running seq %u\n", iop->img_max_size, iop->bl_size, iop->running_seq); return seq; } seq = ota_update_seq_policy[iop->running_seq]; /* update sequence */ OTA_DBG("%s(), update seq %d\n", __func__, seq); return seq; }
/** * @brief Reboot system * @return None */ void ota_reboot(void) { OTA_DBG("OTA reboot.\n"); HAL_WDG_Reboot(); }
/** * @brief Verify the image file and modify OTA configuration correspondingly * @param[in] verify Verification algorithm * @param[in] value Pointer to standard value of the verification algorithm * @retval ota_status_t, OTA_STATUS_OK on success */ ota_status_t ota_verify_image(ota_verify_t verify, uint32_t *value) { ota_status_t status; image_cfg_t cfg; image_seq_t seq; if ((verify != OTA_VERIFY_NONE) && (value == NULL)) { OTA_ERR("invalid args, verify %d, res %p\n", verify, value); return OTA_STATUS_ERROR; } seq = ota_get_update_seq(); if (seq >= IMAGE_SEQ_NUM) { return OTA_STATUS_ERROR; } if (ota_priv.get_size == 0) { OTA_ERR("need to get image, get_size %#x\n", ota_priv.get_size); return OTA_STATUS_ERROR; } OTA_DBG("%s(), verify %d, size %#x\n", __func__, verify, ota_priv.get_size); switch (verify) { case OTA_VERIFY_NONE: status = ota_verify_image_none(seq, value); break; #if OTA_OPT_EXTRA_VERIFY_CRC32 case OTA_VERIFY_CRC32: status = ota_verify_image_crc32(seq, value); break; #endif #if OTA_OPT_EXTRA_VERIFY_MD5 case OTA_VERIFY_MD5: status = ota_verify_image_md5(seq, value); break; #endif #if OTA_OPT_EXTRA_VERIFY_SHA1 case OTA_VERIFY_SHA1: status = ota_verify_image_sha1(seq, value); break; #endif #if OTA_OPT_EXTRA_VERIFY_SHA256 case OTA_VERIFY_SHA256: status = ota_verify_image_sha256(seq, value); break; #endif default: OTA_ERR("invalid verify %d\n", verify); return OTA_STATUS_ERROR; } if (status != OTA_STATUS_OK) { OTA_ERR("verify fail, status %d, verify %d\n", status, verify); return OTA_STATUS_ERROR; } cfg.seq = seq; cfg.state = IMAGE_STATE_VERIFIED; return (image_set_cfg(&cfg) == 0 ? OTA_STATUS_OK : OTA_STATUS_ERROR); }
static ota_status_t ota_update_image_process(image_seq_t seq, void *url, ota_update_init_t init_cb, ota_update_get_t get_cb) { ota_status_t status; uint32_t flash; uint32_t addr; uint32_t bl_size; uint32_t recv_size; uint32_t img_max_size; uint8_t *ota_buf; uint8_t eof_flag; uint32_t debug_size; ota_status_t ret = OTA_STATUS_ERROR; const image_ota_param_t *iop = ota_priv.iop; flash = iop->flash[seq]; addr = iop->addr[seq]; img_max_size = iop->img_max_size; OTA_DBG("%s(), seq %d, flash %u, addr %#x\n", __func__, seq, flash, addr); OTA_SYSLOG("OTA: erase flash...\n"); if (flash_erase(flash, addr, img_max_size) != 0) { return ret; } OTA_DBG("%s(), erase flash success\n", __func__); ota_buf = ota_malloc(OTA_BUF_SIZE); if (ota_buf == NULL) { OTA_ERR("no mem\n"); return ret; } if (init_cb(url) != OTA_STATUS_OK) { OTA_ERR("ota update init failed\n"); goto ota_err; } OTA_SYSLOG("OTA: start loading image...\n"); debug_size = OTA_UPDATE_DEBUG_SIZE_UNIT; ota_priv.get_size = 0; /* skip bootloader */ bl_size = iop->bl_size; while (bl_size > 0) { status = get_cb(ota_buf, (bl_size > OTA_BUF_SIZE) ? OTA_BUF_SIZE : bl_size, &recv_size, &eof_flag); if ((status != OTA_STATUS_OK) || eof_flag) { OTA_ERR("status %d, eof %d\n", status, eof_flag); goto ota_err; } bl_size -= recv_size; ota_priv.get_size += recv_size; if (ota_priv.get_size >= debug_size) { OTA_SYSLOG("OTA: loading image (%u KB)...\n", ota_priv.get_size / 1024); debug_size += OTA_UPDATE_DEBUG_SIZE_UNIT; } } OTA_DBG("%s(), skip bootloader success\n", __func__); if (HAL_Flash_Open(flash, OTA_FLASH_TIMEOUT) != HAL_OK) { OTA_ERR("open flash %u fail\n", flash); goto ota_err; } OTA_DBG("image max size %u\n", img_max_size); #if OTA_IMG_DATA_CORRUPTION_TEST OTA_SYSLOG("ota img data corruption test start, pls power down the device\n"); #endif while (img_max_size > 0) { status = get_cb(ota_buf, (img_max_size > OTA_BUF_SIZE) ? OTA_BUF_SIZE : img_max_size, &recv_size, &eof_flag); if (status != OTA_STATUS_OK) { OTA_ERR("status %d\n", status); break; } img_max_size -= recv_size; ota_priv.get_size += recv_size; if (HAL_Flash_Write(flash, addr, ota_buf, recv_size) != HAL_OK) { OTA_ERR("write flash fail, flash %u, addr %#x, size %#x\n", flash, addr, recv_size); break; } addr += recv_size; if (eof_flag) { ret = OTA_STATUS_OK; break; } if (ota_priv.get_size >= debug_size) { OTA_SYSLOG("OTA: loading image (%u KB)...\n", ota_priv.get_size / 1024); debug_size += OTA_UPDATE_DEBUG_SIZE_UNIT; } } #if OTA_IMG_DATA_CORRUPTION_TEST OTA_SYSLOG("ota img data corruption test end\n"); #endif HAL_Flash_Close(flash); ota_err: if (ota_buf) ota_free(ota_buf); if (ret != OTA_STATUS_OK) { if (img_max_size == 0) { /* reach max size, but not end, continue trying to check sections */ OTA_ERR("download img size %u == %u, but not end\n", ota_priv.get_size - iop->bl_size, iop->img_max_size); } else { return ret; } } OTA_SYSLOG("OTA: finish loading image(%#010x)\n", ota_priv.get_size); if (image_check_sections(seq) == IMAGE_INVALID) { OTA_ERR("ota check image failed\n"); return OTA_STATUS_ERROR; } OTA_SYSLOG("OTA: finish checking image.\n"); return OTA_STATUS_OK; }
/*! process the message methdd, it will be called by ota task. \param[in] handle ota handle \param[in] p_msg new message */ static void ts_ota_single_step(class_handle_t p_handler, os_msg_t *p_msg) { ts_ota_handle_t *p_handle = (ts_ota_handle_t *)p_handler; ts_ota_policy_t *p_policy = p_handle->p_policy; ts_ota_priv_data_t *p_priv = &p_handle->data; dvb_section_t *p_sec = NULL; u16 data_len = 0; void *p_buffer = NULL; if(p_msg != NULL) { switch(p_msg->content) { case TS_OTA_CMD_RELOCK: memcpy((void *)(&p_priv->download_info), (void *)p_msg->para1, sizeof(ts_download_info_t)); p_priv->otai.ota_tri = OTA_TRI_FORC; p_priv->sm = TS_OTA_SM_LOCKING; break; case TS_OTA_CMD_START: p_policy->read_otai(&p_priv->otai); if(p_priv->otai.ota_tri == OTA_TRI_AUTO) { //auto ota. p_priv->download_info.polar = p_priv->otai.locks.tp_rcv.polarity; p_priv->download_info.channel_info.frequency = dvbs_calc_mid_freq(&(p_priv->otai.locks.tp_rcv), &(p_priv->otai.locks.sat_rcv)); p_priv->download_info.channel_info.param.dvbs.symbol_rate = p_priv->otai.locks.tp_rcv.sym; p_priv->download_info.channel_info.param.dvbs.fec_inner = NIM_CR_AUTO; p_priv->download_info.pid = p_priv->otai.download_data_pid; OTA_DBG(("Auto mode: f[%d], s[%d], data_pid[%d]\n", p_priv->download_info.channel_info.frequency, p_priv->download_info.channel_info.param.dvbs.symbol_rate, p_priv->download_info.pid)); p_priv->sm = TS_OTA_SM_LOCKING; } else if(p_priv->otai.ota_tri == OTA_TRI_FORC) { OTA_DBG(("force ota, to open user input menu.\n")); send_msg_to_ui(TS_OTA_EVT_UNLOCKED, 0, 0); p_priv->sm = TS_OTA_SM_IDLE; } break; case TS_OTA_CMD_STOP: OTA_DBG(("stop OTA and restart\n")); p_priv->otai.ota_tri = OTA_TRI_NONE; p_policy->write_otai(&p_priv->otai); #ifndef WIN32 mtos_task_delay_ms(1000); hal_pm_reset(); #endif p_priv->sm = TS_OTA_SM_IDLE; break; case TS_OTA_CMD_START_SEARCH: send_msg_to_ui(TS_OTA_EVT_STATUS, (u32)"start request sdt...", 0); memcpy(&p_priv->otai, (ota_info_t *)p_msg->para1, sizeof(ota_info_t)); p_priv->svc_id = TS_OTA_INVALID_SID; sdt_request(p_priv, 0); p_priv->sm = TS_OTA_SM_IDLE; break; case TS_OTA_CMD_STOP_SEARCH: if(p_msg->para1) { p_priv->otai.ota_tri = OTA_TRI_AUTO; p_policy->write_otai(&(p_priv->otai)); send_msg_to_ui(TS_OTA_EVT_STOPPED, 0, 0); send_msg_to_ui(TS_OTA_EVT_RESET, 0, 0); } else { send_msg_to_ui(TS_OTA_EVT_STOPPED, 0, 0); } p_priv->sm = TS_OTA_SM_IDLE; break; case DVB_PAT_FOUND: OTA_DBG(("ts ota: pat found\n")); break; case DVB_SDT_FOUND: send_msg_to_ui(TS_OTA_EVT_STATUS, (u32)"sdt found", 0); on_ts_ota_sdt_found(p_handle, p_msg); break; case DVB_PAT_PMT_INFO: OTA_DBG(("ts ota: pat pmt info\n")); on_ts_ota_pmt_info_found(p_handle, p_msg); break; case DVB_PMT_FOUND: send_msg_to_ui(TS_OTA_EVT_STATUS, (u32)"pmt found", 0); on_ts_ota_pmt_found(p_handle, p_msg); if(p_priv->otai.ota_tri == OTA_TRI_FORC) { send_msg_to_ui(TS_OTA_EVT_STATUS, (u32)"request ts paket...", 0); p_buffer = mtos_malloc(TS_OTA_TS_PACKET_SIZE); MT_ASSERT(p_buffer != NULL); request_ts_ota_packet(p_priv, p_buffer); p_priv->sm = TS_OTA_SM_DOWLOAD; } else { send_msg_to_ui(TS_OTA_EVT_FOUND, 0, 0); p_priv->sm = TS_OTA_SM_IDLE; } break; case DVB_ONE_SEC_FOUND: OTA_DBG(("DVB_ONE_SEC_FOUND\n")); data_len = (u16)(p_msg->para2 & 0xFFFF); p_sec = (dvb_section_t *)p_msg->para1; if(DVB_TABLE_ID_OTA_TS == p_sec->table_id) { //notify ts for the data. //ts_ota_Section_Notify(p_sec->p_buffer); } break; case DVB_TABLE_TIMED_OUT: switch(p_msg->para1) { case DVB_TABLE_ID_PAT: OTA_DBG(("ts ota: pat timeout\n")); pat_request(p_priv); break; case DVB_TABLE_ID_SDT_ACTUAL: OTA_DBG(("ts ota: sdt timeout, retry\n")); on_ts_ota_sdt_time_out(p_handle, p_msg); break; case DVB_TABLE_ID_PMT: OTA_DBG(("ts ota: pmt timeout\n")); pmt_request(p_priv, p_msg->context); break; default: break; } break; default: break; } } else { switch(p_priv->sm) { case TS_OTA_SM_IDLE: //mtos_task_sleep(100); break; case TS_OTA_SM_LOCKING: dev_io_ctrl(p_priv->p_nim, NIM_IOCTRL_SET_PORLAR, p_priv->download_info.polar); nim_channel_connect(p_priv->p_nim, &(p_priv->download_info.channel_info), FALSE); if(p_priv->download_info.channel_info.lock) { send_msg_to_ui(TS_OTA_EVT_LOCKED, 0, 0); if(p_priv->otai.ota_tri == OTA_TRI_AUTO) { p_priv->sm = TS_OTA_SM_DOWLOAD; p_buffer = mtos_malloc(TS_OTA_TS_PACKET_SIZE); MT_ASSERT(p_buffer != NULL); request_ts_ota_packet(p_priv, p_buffer); } else { p_priv->sm = TS_OTA_SM_SEARCHING; } } else { send_msg_to_ui(TS_OTA_EVT_UNLOCKED, 0, 0); p_priv->sm = TS_OTA_SM_IDLE; } break; case TS_OTA_SM_SEARCHING: p_priv->svc_id = TS_OTA_INVALID_SID; sdt_request(p_priv, 0); p_priv->sm = TS_OTA_SM_IDLE; break; case TS_OTA_SM_DOWLOAD: break; default: break; } } }