/***************************************************************************** * * File Name : wm_fwup.c * * Description: firmware update Module * * Copyright (c) 2014 Winner Micro Electronic Design Co., Ltd. * All rights reserved. * * Author : dave * * Date : 2014-6-16 *****************************************************************************/ #include #include #include #include "wm_mem.h" #include "list.h" #include "wm_debug.h" #include "wm_internal_flash.h" #include "wm_flash.h" #include "wm_crypto_hard.h" #include "utils.h" #include "wm_fwup.h" #include "wm_watchdog.h" #include "wm_wifi.h" #include "wm_flash_map.h" #include "wm_wl_task.h" #include "wm_params.h" #include "wm_param.h" #define FWUP_MSG_QUEUE_SIZE (4) #define FWUP_TASK_STK_SIZE (512) #define FWUP_MSG_START_ENGINEER (1) static struct tls_fwup *fwup = NULL; static tls_os_queue_t *fwup_msg_queue = NULL; static u32 fwup_task_stk[FWUP_TASK_STK_SIZE]; //static u8 oneshotback = 0; static u8 *fwupwritebuffer = NULL; T_BOOTER imgheader[2]; extern u32 flashtotalsize; static void fwup_update_autoflag(void) { u8 auto_reconnect = 0xff; tls_wifi_auto_connect_flag(WIFI_AUTO_CNT_FLAG_GET, &auto_reconnect); if(auto_reconnect == WIFI_AUTO_CNT_TMP_OFF) { auto_reconnect = WIFI_AUTO_CNT_ON; tls_wifi_auto_connect_flag(WIFI_AUTO_CNT_FLAG_SET, &auto_reconnect); } return; } int tls_fwup_img_header_check(T_BOOTER *img_param) { psCrcContext_t crcContext; u32 value = 0; int i = 0; u32 runaddr = 0; u32 updaddr = 0; if (img_param->magic_no != SIGNATURE_WORD) { return FALSE; } if ((IMG_TYPE_OLD_PLAIN != img_param->img_type) && (IMG_TYPE_NEW_PLAIN != img_param->img_type)) { return FALSE; } tls_crypto_crc_init(&crcContext, 0xFFFFFFFF, CRYPTO_CRC_TYPE_32, 3); for (i = 0; i < (sizeof(T_BOOTER)-4)/4; i++) { value = *(((int *)img_param)+i); tls_crypto_crc_update(&crcContext, (unsigned char *)&value, 4); } value = 0; tls_crypto_crc_final(&crcContext, &value); runaddr = img_param->run_img_addr|FLASH_BASE_ADDR; if ((img_param->hd_checksum == value) && (runaddr < FLASH_1M_END_ADDR)) { /*forbid 1M_Plain and 2M_PLAIN update*/ tls_fls_read(CODE_RUN_HEADER_ADDR, (unsigned char *)&imgheader[0], sizeof(T_BOOTER)); if (imgheader[0].img_type != img_param->img_type) { return FALSE; } /*run addr must be page-aligned in first 1M flash */ if ((runaddr % INSIDE_FLS_PAGE_SIZE) || (0 == img_param->run_img_len) || (runaddr + img_param->run_img_len >= FLASH_1M_END_ADDR) || (runaddr < CODE_RUN_START_ADDR)) { return FALSE; } /*can not upd over flash size minus system parameter area*/ value = runaddr + img_param->run_img_len; if (value < imgheader[0].run_img_addr + imgheader[0].run_img_len) { value = (imgheader[0].run_img_addr|FLASH_BASE_ADDR) + imgheader[0].run_img_len; } value = value%INSIDE_FLS_BLOCK_SIZE ? (value/INSIDE_FLS_BLOCK_SIZE)*INSIDE_FLS_BLOCK_SIZE + INSIDE_FLS_BLOCK_SIZE : value; updaddr = img_param->upd_img_addr|FLASH_BASE_ADDR; /*upd address can not overlap run addr & must be 64K aligned*/ if ((updaddr < value) || (updaddr%INSIDE_FLS_BLOCK_SIZE) || (0 == img_param->upd_img_len)) { return FALSE; } if(updaddr != 0x08100000 || img_param->upd_img_len > 0xbfc00) { printf("tampered with OTA header!\n"); return FALSE; } /*over flash capacity decrease one block size used as sys param area*/ if ((updaddr + img_param->upd_img_len) > ((flashtotalsize - INSIDE_FLS_BLOCK_SIZE)|FLASH_BASE_ADDR)) { return FALSE; } return TRUE; } else { return FALSE; } } static void tls_fwup_img_update_header(T_BOOTER* img_param) { unsigned char current_img; psCrcContext_t crcContext; tls_fls_read(CODE_RUN_HEADER_ADDR, (unsigned char *)&imgheader[0], sizeof(T_BOOTER)); tls_fls_read(CODE_UPD_HEADER_ADDR, (unsigned char *)&imgheader[1], sizeof(T_BOOTER)); //将两个upd_no中较大的那个值取出来,再将其加1后赋值给 CODE_UPD_HEADER_ADDR 处的header; if (tls_fwup_img_header_check(&imgheader[1])) { current_img = (imgheader[1].upd_no > imgheader[0].upd_no); } else { current_img = 0; } img_param->upd_no = imgheader[current_img].upd_no + 1; tls_crypto_crc_init(&crcContext, 0xFFFFFFFF, CRYPTO_CRC_TYPE_32, 3); tls_crypto_crc_update(&crcContext, (unsigned char *)img_param, sizeof(T_BOOTER)-4); tls_crypto_crc_final(&crcContext, &img_param->hd_checksum); tls_fls_write(CODE_UPD_HEADER_ADDR, (unsigned char *)img_param, sizeof(T_BOOTER)); } /* ninlight: SHA256 + tail verification hook instead of the QConnex RSA check (see sdk/PATCHES.md) */ #include "util/nl_sha256.h" #include "sys/nl_fwup_hook.h" #include "sys/nl_ota.h" /* nl_ota_set_error() - see sdk/PATCHES.md point 1 */ static void fwup_scheduler(void *data) { u8 *buffer = NULL; int err; u32 msg; u32 len; u32 image_checksum = 0; u32 org_checksum = 0; struct tls_fwup_request *request; struct tls_fwup_request *temp; T_BOOTER booter; u32 currentlen = 0; u32 tmplen = 0; bool isacrossflash = FALSE; nl_sha256_ctx sha; nl_sha256_init(&sha); u8 image_sha256[32] = {0}; u8 *RSA_SHA256 = NULL; while (1) { err = tls_os_queue_receive(fwup_msg_queue, (void **)&msg, 0, 0); tls_watchdog_clr(); if(err != TLS_OS_SUCCESS) { continue; } switch(msg) { case FWUP_MSG_START_ENGINEER: if(dl_list_empty(&fwup->wait_list) == 0) { fwup->current_state |= TLS_FWUP_STATE_BUSY; } dl_list_for_each_safe(request, temp, &fwup->wait_list, struct tls_fwup_request, list) { request->status = TLS_FWUP_REQ_STATUS_BUSY; if(fwup->current_state & TLS_FWUP_STATE_ERROR) { TLS_DBGPRT_WARNING("some error happened during firmware update, so discard all the request in the waiting queue!\n"); if(fwup->current_state & TLS_FWUP_STATE_ERROR_IO) { request->status = TLS_FWUP_REQ_STATUS_FIO; } else if(fwup->current_state & TLS_FWUP_STATE_ERROR_SIGNATURE) { request->status = TLS_FWUP_REQ_STATUS_FSIGNATURE; } else if(fwup->current_state & TLS_FWUP_STATE_ERROR_MEM) { request->status = TLS_FWUP_REQ_STATUS_FMEM; } else if(fwup->current_state & TLS_FWUP_STATE_ERROR_CRC) { request->status = TLS_FWUP_REQ_STATUS_FCRC; } goto request_finish; } else if(fwup->current_state & TLS_FWUP_STATE_COMPLETE) { TLS_DBGPRT_WARNING("the firmware updating conpletes, so discard the request in the waiting queue!\n"); request->status = TLS_FWUP_REQ_STATUS_FCOMPLETE; goto request_finish; } if(fwup->current_image_src <= TLS_FWUP_IMAGE_SRC_WEB) { buffer = request->data; if(fwup->received_len < sizeof(T_BOOTER)) { len = sizeof(T_BOOTER) - fwup->received_len; if(request->data_len < len) { len = request->data_len; } MEMCPY(&booter, buffer, sizeof(T_BOOTER)); request->data_len -= len; buffer += len; fwup->received_len += len; if(fwup->received_len == sizeof(T_BOOTER)) { if (!tls_fwup_img_header_check(&booter)) { request->status = TLS_FWUP_REQ_STATUS_FIO; fwup->current_state |= TLS_FWUP_STATE_ERROR_IO; goto request_finish; } nl_sha256_update(&sha, (u8*)&booter, sizeof(T_BOOTER)); if ((IMG_TYPE_OLD_PLAIN == booter.img_type ) ||(IMG_TYPE_NEW_PLAIN == booter.img_type)) { fwup->program_base = booter.upd_img_addr | FLASH_BASE_ADDR; fwup->total_len = booter.upd_img_len + 512; org_checksum = booter.upd_checksum; isacrossflash = FALSE; currentlen = 0; } else { request->status = TLS_FWUP_REQ_STATUS_FCRC; goto request_finish; } fwup->updated_len = 0; } } fwup->received_len += request->data_len; } if ((request->data_len > 0) && (fwupwritebuffer)) { if((currentlen + request->data_len) < INSIDE_FLS_SECTOR_SIZE) { memcpy(fwupwritebuffer + currentlen, buffer, request->data_len); currentlen += request->data_len; fwup->updated_len += request->data_len; } else { if ((IMG_TYPE_OLD_PLAIN == booter.img_type) \ && (0x200000 == flashtotalsize)\ && (fwup->program_base < FLASH_1M_END_ADDR)\ && ((fwup->program_base + fwup->updated_len) >= (FLASH_1M_END_ADDR - INSIDE_FLS_BLOCK_SIZE))) { isacrossflash = TRUE; fwup->program_base = FLASH_1M_END_ADDR; fwup->program_offset = 0; } //TLS_DBGPRT_INFO("write the firmware image to the flash. %x\n\r", fwup->program_base + fwup->program_offset); memcpy(fwupwritebuffer + currentlen, buffer, (INSIDE_FLS_SECTOR_SIZE - currentlen)); tmplen = fwup->program_offset/INSIDE_FLS_SECTOR_SIZE * INSIDE_FLS_SECTOR_SIZE; err = tls_fls_write(fwup->program_base + tmplen, fwupwritebuffer, INSIDE_FLS_SECTOR_SIZE); if(err != TLS_FLS_STATUS_OK) { TLS_DBGPRT_ERR("failed to program flash!\n"); request->status = TLS_FWUP_REQ_STATUS_FIO; fwup->current_state |= TLS_FWUP_STATE_ERROR_IO; goto request_finish; } memcpy(fwupwritebuffer, buffer + (INSIDE_FLS_SECTOR_SIZE - currentlen), (currentlen + request->data_len) - INSIDE_FLS_SECTOR_SIZE); fwup->program_offset += INSIDE_FLS_SECTOR_SIZE; fwup->updated_len += request->data_len; currentlen = (currentlen + request->data_len) - INSIDE_FLS_SECTOR_SIZE; } //TLS_DBGPRT_INFO("updated: %d bytes\n" , fwup->updated_len); if(fwup->updated_len >= fwup->total_len) { u32 left = 0, offset = 0; psCrcContext_t crcContext; if (fwup->program_offset <= fwup->updated_len) { if ((IMG_TYPE_OLD_PLAIN == booter.img_type) \ && (0x200000 == flashtotalsize)\ && (fwup->program_base < FLASH_1M_END_ADDR)\ && ((fwup->program_base + fwup->updated_len) >= (FLASH_1M_END_ADDR - INSIDE_FLS_BLOCK_SIZE))) { isacrossflash = TRUE; fwup->program_base = FLASH_1M_END_ADDR; fwup->program_offset = 0; } err = tls_fls_write(fwup->program_base + fwup->program_offset, fwupwritebuffer, currentlen); if(err != TLS_FLS_STATUS_OK) { TLS_DBGPRT_ERR("failed to program flash!\n"); request->status = TLS_FWUP_REQ_STATUS_FIO; fwup->current_state |= TLS_FWUP_STATE_ERROR_IO; goto request_finish; } } offset = 0; fwup->program_base = booter.upd_img_addr | FLASH_BASE_ADDR; if (TRUE == isacrossflash) { left = (FLASH_1M_END_ADDR - INSIDE_FLS_BLOCK_SIZE) - fwup->program_base; } else { left = fwup->total_len - 512; } tls_crypto_crc_init(&crcContext, 0xFFFFFFFF, CRYPTO_CRC_TYPE_32, 3); while (left > 0) { len = left > INSIDE_FLS_SECTOR_SIZE ? INSIDE_FLS_SECTOR_SIZE : left; err = tls_fls_read(fwup->program_base + offset, fwupwritebuffer, len); if (err != TLS_FLS_STATUS_OK) { request->status = TLS_FWUP_REQ_STATUS_FIO; fwup->current_state |= TLS_FWUP_STATE_ERROR_IO; goto request_finish; } tls_crypto_crc_update(&crcContext, fwupwritebuffer, len); nl_sha256_update(&sha, fwupwritebuffer, len); offset += len; left -= len; } if (TRUE == isacrossflash) { left = fwup->total_len - offset; fwup->program_base = FLASH_1M_END_ADDR; offset = 0; while (left > 0) { len = left > INSIDE_FLS_SECTOR_SIZE ? INSIDE_FLS_SECTOR_SIZE : left; err = tls_fls_read(fwup->program_base + offset, fwupwritebuffer, len); if (err != TLS_FLS_STATUS_OK) { request->status = TLS_FWUP_REQ_STATUS_FIO; fwup->current_state |= TLS_FWUP_STATE_ERROR_IO; goto request_finish; } tls_crypto_crc_update(&crcContext, fwupwritebuffer, len); nl_sha256_update(&sha, fwupwritebuffer, len); offset += len; left -= len; } } tls_crypto_crc_final(&crcContext, &image_checksum); nl_sha256_final(&sha, image_sha256); #if 0 printf("last sector - len:%d isacrossflash: %d\n", len, isacrossflash); u8 *bptr = (u8*)fwupwritebuffer; for (int i = 0; i < 32; ++i) printf("%02x ", bptr[i]); printf("\n"); #endif // now read last 256 byte - with RSA encoded SHA256 left = 512; RSA_SHA256 = tls_mem_alloc(left); if(!RSA_SHA256) { goto request_finish; } while (left > 0) { len = left > INSIDE_FLS_SECTOR_SIZE ? INSIDE_FLS_SECTOR_SIZE : left; err = tls_fls_read(fwup->program_base + offset, RSA_SHA256, len); if (err != TLS_FLS_STATUS_OK) { request->status = TLS_FWUP_REQ_STATUS_FIO; fwup->current_state |= TLS_FWUP_STATE_ERROR_IO; goto request_finish; } offset += len; left -= len; } #if 0 bptr = (u8*)RSA_SHA256; printf("start enc hash - len:%d\n", len); for (int i = 0; i < 32; ++i) printf("%02x ", bptr[i]); printf("\n"); #endif if (org_checksum != image_checksum) // QC_CHANGE_MK { /* ninlight: a checksum failure never reaches nl_fwup_verify_tail() below, * so report it here explicitly - otherwise last_ota_error would fall back * to the generic "download" instead of the more precise "crc" (see * sdk/PATCHES.md point 1). */ TLS_DBGPRT_ERR("varify incorrect[0x%02x, but 0x%02x]\n", org_checksum, image_checksum); nl_ota_set_error("crc"); request->status = TLS_FWUP_REQ_STATUS_FCRC; fwup->current_state |= TLS_FWUP_STATE_ERROR_CRC; goto request_finish; } else if (!nl_fwup_verify_tail(image_sha256, RSA_SHA256, 512)) // QC_CHANGE_MK { request->status = TLS_FWUP_REQ_STATUS_FCRC; fwup->current_state |= TLS_FWUP_STATE_ERROR_CRC; goto request_finish; } else /*CRC MATCH and Update IMAGE HEADER PARAM*/ { tls_fwup_img_update_header(&booter); } TLS_DBGPRT_INFO("update the firmware successfully!\n"); fwup->current_state |= TLS_FWUP_STATE_COMPLETE; //if (oneshotback == 1){ // tls_wifi_set_oneshot_flag(oneshotback); // 恢复一键配置 //} } } request->status = TLS_FWUP_REQ_STATUS_SUCCESS; request_finish: if(RSA_SHA256) { tls_mem_free(RSA_SHA256); } tls_os_sem_acquire(fwup->list_lock, 0); dl_list_del(&request->list); tls_os_sem_release(fwup->list_lock); if(dl_list_empty(&fwup->wait_list) == 1) { fwup->current_state &= ~TLS_FWUP_STATE_BUSY; } if(request->complete) { request->complete(request, request->arg); } /* ninlight: only reset when the image was actually accepted. Before this fix the * condition below fired unconditionally once the transfer reached its end - * including a request that got rejected by nl_fwup_verify_tail() (trailer/device/ * hash mismatch) or by the checksum check above (goto request_finish also lands * here). Resetting in that case would reboot into the OLD firmware and never let * ota_task() report the failure - so last_ota_error stayed NULL forever. See * sdk/PATCHES.md point 1. */ if(fwup->updated_len >= (fwup->total_len) && !(fwup->current_state & TLS_FWUP_STATE_ERROR)) { fwup_update_autoflag(); tls_sys_reset(); } } break; default: break; } } } void fwup_request_complete(struct tls_fwup_request *request, void *arg) { tls_os_sem_t *sem; if((request == NULL) || (arg == NULL)) { return; } sem = (tls_os_sem_t *)arg; tls_os_sem_release(sem); } u32 tls_fwup_enter(enum tls_fwup_image_src image_src) { u32 session_id = 0; u32 cpu_sr; tls_fwup_init(); if (fwup == NULL) { TLS_DBGPRT_INFO("fwup is null!\n"); return 0; } if (fwup->busy == TRUE) { TLS_DBGPRT_INFO("fwup is busy!\n"); return 0; } cpu_sr = tls_os_set_critical(); do { session_id = rand(); }while(session_id == 0); if (NULL == fwupwritebuffer) { fwupwritebuffer = tls_mem_alloc(INSIDE_FLS_SECTOR_SIZE); if (NULL == fwupwritebuffer) { tls_os_release_critical(cpu_sr); return 0; } } fwup->current_state = 0; fwup->current_image_src = image_src; fwup->received_len = 0; fwup->total_len = 0; fwup->updated_len = 0; fwup->program_base = 0; fwup->program_offset = 0; fwup->received_number = -1; fwup->current_session_id = session_id; fwup->busy = TRUE; tls_os_release_critical(cpu_sr); //oneshotback = tls_wifi_get_oneshot_flag(); //if (oneshotback == 1){ // tls_wifi_set_oneshot_flag(0); // 退出一键配置 //} tls_wifi_set_psflag(FALSE, 0); return session_id; } int tls_fwup_exit(u32 session_id) { u32 cpu_sr; bool enable = FALSE; //tls_os_task_t fwtask; //tls_os_status_t osstatus = 0; if ((fwup == NULL) || (fwup->busy == FALSE)) { return TLS_FWUP_STATUS_EPERM; } if (session_id != fwup->current_session_id) { return TLS_FWUP_STATUS_ESESSIONID; } if (fwup->current_state & TLS_FWUP_STATE_BUSY) { return TLS_FWUP_STATUS_EBUSY; } cpu_sr = tls_os_set_critical(); if (fwupwritebuffer) { tls_mem_free(fwupwritebuffer); fwupwritebuffer = NULL; } fwup->current_state = 0; fwup->received_len = 0; fwup->total_len = 0; fwup->updated_len = 0; fwup->program_base = 0; fwup->program_offset = 0; fwup->received_number = -1; fwup->current_session_id = 0; fwup->busy = FALSE; tls_os_release_critical(cpu_sr); //if (oneshotback == 1){ // tls_wifi_set_oneshot_flag(oneshotback); // 恢复一键配置 //} tls_param_get(TLS_PARAM_ID_PSM, &enable, TRUE); tls_wifi_set_psflag(enable, 0); return TLS_FWUP_STATUS_OK; } int tls_fwup_get_current_session_id(void) { if (fwup){ return fwup->current_session_id; } return 0; } int tls_fwup_set_update_numer(int number) { if(1 == number - fwup->received_number) { fwup->received_number = number; return TLS_FWUP_STATUS_OK; } return TLS_FWUP_STATE_UNDEF; } int tls_fwup_get_current_update_numer(void) { return fwup->received_number; } int tls_fwup_get_status(void) { return fwup->busy; } int tls_fwup_set_crc_error(u32 session_id) { if(fwup == NULL) { return TLS_FWUP_STATUS_EPERM; } if(session_id != fwup->current_session_id) { return TLS_FWUP_STATUS_ESESSIONID; } fwup->current_state |= TLS_FWUP_STATE_ERROR_CRC; return TLS_FWUP_STATUS_OK; } static int tls_fwup_request_async(u32 session_id, struct tls_fwup_request *request) { u8 need_sched; if(fwup == NULL) { return TLS_FWUP_STATUS_EPERM; } if(session_id != fwup->current_session_id) { return TLS_FWUP_STATUS_ESESSIONID; } if((request == NULL) || (request->data == NULL) || (request->data_len == 0)) { return TLS_FWUP_STATUS_EINVALID; } tls_os_sem_acquire(fwup->list_lock, 0); if(dl_list_empty(&fwup->wait_list)) { need_sched = 1; } else { need_sched = 0; } request->status = TLS_FWUP_REQ_STATUS_IDLE; dl_list_add_tail(&fwup->wait_list, &request->list); tls_os_sem_release(fwup->list_lock); if(need_sched == 1) { tls_os_queue_send(fwup_msg_queue, (void *)FWUP_MSG_START_ENGINEER, 0); } return TLS_FWUP_STATUS_OK; } int tls_fwup_request_sync(u32 session_id, u8 *data, u32 data_len) { int err; tls_os_sem_t *sem; struct tls_fwup_request request; if(fwup == NULL) { return TLS_FWUP_STATUS_EPERM; } if(session_id != fwup->current_session_id) { return TLS_FWUP_STATUS_ESESSIONID; } if((data == NULL) || (data_len == 0)) { return TLS_FWUP_STATUS_EINVALID; } err = tls_os_sem_create(&sem, 0); if(err != TLS_OS_SUCCESS) { return TLS_FWUP_STATUS_EMEM; } request.data = data; request.data_len = data_len; request.complete = fwup_request_complete; request.arg = (void *)sem; tls_wifi_set_psflag(FALSE, 0); err = tls_fwup_request_async(session_id, &request); if(err == TLS_FWUP_STATUS_OK) { tls_os_sem_acquire(sem, 0); } tls_os_sem_delete(sem); switch(request.status) { case TLS_FWUP_REQ_STATUS_SUCCESS: err = TLS_FWUP_STATUS_OK; break; case TLS_FWUP_REQ_STATUS_FIO: err = TLS_FWUP_STATUS_EIO; break; case TLS_FWUP_REQ_STATUS_FSIGNATURE: err = TLS_FWUP_STATUS_ESIGNATURE; break; case TLS_FWUP_REQ_STATUS_FMEM: err = TLS_FWUP_STATUS_EMEM; break; case TLS_FWUP_REQ_STATUS_FCRC: err = TLS_FWUP_STATUS_ECRC; break; case TLS_FWUP_REQ_STATUS_FCOMPLETE: err = TLS_FWUP_STATUS_EIO; break; default: err = TLS_FWUP_STATUS_EUNDEF; break; } return err; } u16 tls_fwup_current_state(u32 session_id) { if(fwup == NULL) { return TLS_FWUP_STATE_UNDEF; } if(session_id != fwup->current_session_id) { return TLS_FWUP_STATE_UNDEF; } return fwup->current_state; } int tls_fwup_reset(u32 session_id) { u32 cpu_sr; if ((fwup == NULL) || (fwup->busy == FALSE)) {return TLS_FWUP_STATUS_EPERM;} if (session_id != fwup->current_session_id) {return TLS_FWUP_STATUS_ESESSIONID;} if (fwup->current_state & TLS_FWUP_STATE_BUSY) {return TLS_FWUP_STATUS_EBUSY;} cpu_sr = tls_os_set_critical(); fwup->current_state = 0; fwup->received_len = 0; fwup->total_len = 0; fwup->updated_len = 0; fwup->program_base = 0; fwup->program_offset = 0; tls_os_release_critical(cpu_sr); return TLS_FWUP_STATUS_OK; } int tls_fwup_clear_error(u32 session_id) { u32 cpu_sr; if ((fwup == NULL) || (fwup->busy == FALSE)) {return TLS_FWUP_STATUS_EPERM;} if (session_id != fwup->current_session_id) {return TLS_FWUP_STATUS_ESESSIONID;} if (fwup->current_state & TLS_FWUP_STATE_BUSY) {return TLS_FWUP_STATUS_EBUSY;} cpu_sr = tls_os_set_critical(); fwup->current_state &= ~TLS_FWUP_STATE_ERROR; tls_os_release_critical(cpu_sr); return TLS_FWUP_STATUS_OK; } int tls_fwup_init(void) { int err; if(fwup != NULL) { TLS_DBGPRT_ERR("firmware update module has been installed!\n"); return TLS_FWUP_STATUS_EBUSY; } fwup = tls_mem_alloc(sizeof(*fwup)); if(fwup == NULL) { TLS_DBGPRT_ERR("allocate @fwup fail!\n"); return TLS_FWUP_STATUS_EMEM; } memset(fwup, 0, sizeof(*fwup)); err = tls_os_sem_create(&fwup->list_lock, 1); if(err != TLS_OS_SUCCESS) { TLS_DBGPRT_ERR("create semaphore @fwup->list_lock fail!\n"); tls_mem_free(fwup); return TLS_FWUP_STATUS_EMEM; } dl_list_init(&fwup->wait_list); fwup->busy = FALSE; err = tls_os_queue_create(&fwup_msg_queue, FWUP_MSG_QUEUE_SIZE); if (err != TLS_OS_SUCCESS) { TLS_DBGPRT_ERR("create message queue @fwup_msg_queue fail!\n"); tls_os_sem_delete(fwup->list_lock); tls_mem_free(fwup); return TLS_FWUP_STATUS_EMEM; } err = tls_os_task_create(NULL, "fwup", fwup_scheduler, (void *)fwup, (void *)&fwup_task_stk[0], FWUP_TASK_STK_SIZE * sizeof(u32), TLS_FWUP_TASK_PRIO, 0); if (err != TLS_OS_SUCCESS) { TLS_DBGPRT_ERR("create firmware update process task fail!\n"); tls_os_queue_delete(fwup_msg_queue); tls_os_sem_delete(fwup->list_lock); tls_mem_free(fwup); return TLS_FWUP_STATUS_EMEM; } return TLS_FWUP_STATUS_OK; } /**Run-time image area size*/ unsigned int CODE_RUN_AREA_LEN = 0; /**Area can be used by User in 1M position*/ unsigned int USER_ADDR_START = 0; unsigned int TLS_FLASH_PARAM_DEFAULT = 0; unsigned int USER_AREA_LEN = 0; unsigned int USER_ADDR_END = 0; /**Upgrade image header area & System parameter area */ unsigned int CODE_UPD_HEADER_ADDR = 0; unsigned int TLS_FLASH_PARAM1_ADDR = 0; unsigned int TLS_FLASH_PARAM2_ADDR = 0; unsigned int TLS_FLASH_PARAM_RESTORE_ADDR = 0; /**Upgrade image area*/ unsigned int CODE_UPD_START_ADDR = 0; unsigned int CODE_UPD_AREA_LEN = 0; /**Area can be used by User in 2M position*/ unsigned int EX_USER_ADDR_START = 0; unsigned int EX_USER_AREA_LEN = 0; unsigned int EX_USER_ADDR_END = 0; unsigned int TLS_FLASH_END_ADDR = 0; void tls_fls_layout_init(void) { T_BOOTER tbooter; tls_fls_read(CODE_RUN_HEADER_ADDR, (u8 *)&tbooter, sizeof(tbooter)); switch (flashtotalsize) { case 0x200000: /*2M*/ { if (IMG_TYPE_OLD_PLAIN == tbooter.img_type) { //printf("2M use old layout\r\n"); /**Run-time image area size*/ CODE_RUN_AREA_LEN = (896*1024 - 256); /**Area can be used by User in 1M position*/ USER_ADDR_START = (CODE_RUN_START_ADDR + CODE_RUN_AREA_LEN); TLS_FLASH_PARAM_DEFAULT = (USER_ADDR_START); USER_AREA_LEN = (48*1024); USER_ADDR_END = (USER_ADDR_START + USER_AREA_LEN - 1); /**Upgrade image header area & System parameter area */ CODE_UPD_HEADER_ADDR = (USER_ADDR_START + USER_AREA_LEN); TLS_FLASH_PARAM1_ADDR = (CODE_UPD_HEADER_ADDR + 0x1000); TLS_FLASH_PARAM2_ADDR = (TLS_FLASH_PARAM1_ADDR + 0x1000); TLS_FLASH_PARAM_RESTORE_ADDR = (TLS_FLASH_PARAM2_ADDR + 0x1000); /**Upgrade image area*/ CODE_UPD_START_ADDR = (TLS_FLASH_PARAM_RESTORE_ADDR + 0x1000); CODE_UPD_AREA_LEN = (704*1024); /**Area can be used by User in 2M position*/ EX_USER_ADDR_START = (CODE_UPD_START_ADDR + CODE_UPD_AREA_LEN); EX_USER_AREA_LEN = (320*1024); EX_USER_ADDR_END = (EX_USER_ADDR_START + EX_USER_AREA_LEN - 1); TLS_FLASH_END_ADDR = (EX_USER_ADDR_END); } else { //printf("2M use new layout\r\n"); /**Run-time image area size*/ CODE_RUN_AREA_LEN = (960*1024 - 256); /**Upgrade image area*/ CODE_UPD_START_ADDR = (CODE_RUN_START_ADDR + CODE_RUN_AREA_LEN); CODE_UPD_AREA_LEN = (768*1024); /**Area can be used by User*/ USER_ADDR_START = (CODE_UPD_START_ADDR + CODE_UPD_AREA_LEN); TLS_FLASH_PARAM_DEFAULT = (USER_ADDR_START); USER_AREA_LEN = (240*1024); USER_ADDR_END = (USER_ADDR_START + USER_AREA_LEN - 1); /**Area can be used by User in 2M position*/ EX_USER_ADDR_START = 0; EX_USER_AREA_LEN = 0; EX_USER_ADDR_END = 0; /**Upgrade image header area & System parameter area */ CODE_UPD_HEADER_ADDR = (USER_ADDR_START + USER_AREA_LEN) ; TLS_FLASH_PARAM1_ADDR = (CODE_UPD_HEADER_ADDR + 0x1000); TLS_FLASH_PARAM2_ADDR = (TLS_FLASH_PARAM1_ADDR + 0x1000); TLS_FLASH_PARAM_RESTORE_ADDR = (TLS_FLASH_PARAM2_ADDR + 0x1000); TLS_FLASH_END_ADDR = (TLS_FLASH_PARAM_RESTORE_ADDR + 0x1000 -1); } } break; default: /*1M*/ { //printf("1M layout\r\n"); /**Run-time image area size*/ CODE_RUN_AREA_LEN = (512*1024 - 256); /**Upgrade image area*/ CODE_UPD_START_ADDR = (CODE_RUN_START_ADDR + CODE_RUN_AREA_LEN); CODE_UPD_AREA_LEN = (384*1024); /**Area can be used by User*/ USER_ADDR_START = (CODE_UPD_START_ADDR + CODE_UPD_AREA_LEN); TLS_FLASH_PARAM_DEFAULT = (USER_ADDR_START); USER_AREA_LEN = (48*1024); USER_ADDR_END = (USER_ADDR_START + USER_AREA_LEN - 1); /**Area can be used by User in 2M position*/ EX_USER_ADDR_START = 0; EX_USER_AREA_LEN = 0; EX_USER_ADDR_END = 0; /**Upgrade image header area & System parameter area */ CODE_UPD_HEADER_ADDR = (USER_ADDR_START + USER_AREA_LEN); TLS_FLASH_PARAM1_ADDR = (CODE_UPD_HEADER_ADDR + 0x1000); TLS_FLASH_PARAM2_ADDR = (TLS_FLASH_PARAM1_ADDR + 0x1000); TLS_FLASH_PARAM_RESTORE_ADDR = (TLS_FLASH_PARAM2_ADDR + 0x1000); TLS_FLASH_END_ADDR = (TLS_FLASH_PARAM_RESTORE_ADDR + 0x1000 - 1); } break; } }