1033 lines
30 KiB
C
1033 lines
30 KiB
C
/*****************************************************************************
|
||
*
|
||
* 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;
|
||
|
||
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)
|
||
{
|
||
/* 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;
|
||
}
|
||
}
|
||
|