Files
ninlight-w600/sdk/Platform/Common/fwup/wm_fwup.c
T
Michael SauerandClaude Opus 5 d56f1d25d2 fix: SHA256-Kontext pro Image initialisieren statt einmal beim Task-Start
Der fwup-Task überlebt jede Update-Sitzung. Weil nl_sha256_init() am
Taskanfang stand, benutzte ab dem zweiten Update-Versuch pro Boot ein
bereits finalisierter Kontext weiter - der Trailer-Hash konnte dann gar
nicht mehr passen und jedes weitere Update scheiterte mit
last_ota_error=hash. Am EVK gefunden: nach einer Ablehnung war ein
Reboot nötig, bevor überhaupt wieder ein Update gelingen konnte.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-12 10:38:01 +02:00

1037 lines
29 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*****************************************************************************
*
* 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 <stdio.h>
#include <string.h>
#include <stdlib.h>
#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;
/* ninlight: the context is (re)initialised per image, where the T_BOOTER header arrives -
* NOT here. This task outlives every update session, so initialising once at task start
* left a finalised context behind after the first attempt and every later update in the
* same boot failed with last_ota_error=hash. Found on the EVK, 2026-09-12. */
nl_sha256_ctx 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_init(&sha); /* fresh context for this image */
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)
{
/* ninlight: this used to jump to request_finish without setting any
* error bit. With the C1 fix (see below / sdk/PATCHES.md point 1) the
* request_finish reset only fires when no error bit is set - so this
* was the one remaining way to reach a reset with the trailer never
* actually checked. Report it like the other allocation failure above. */
request->status = TLS_FWUP_REQ_STATUS_FMEM;
fwup->current_state |= TLS_FWUP_STATE_ERROR_MEM;
nl_ota_set_error("download"); /* no more specific value applies */
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;
}
}