diff --git a/sdk/PATCHES.md b/sdk/PATCHES.md index 86f5868..45d928e 100644 --- a/sdk/PATCHES.md +++ b/sdk/PATCHES.md @@ -70,6 +70,13 @@ Lib/GNU, Bin/secboot.img, Tools/GNU/link_w600_2m.ld (→ ld/) und wm_tool.c (→ exportierte) `session_id`, wäre also ein größerer Eingriff für denselben Effekt. Nebenbei: `nRetCode = ret` (ein lwIP-`err_t` in einer sonst `HTTP_CLIENT_*`-Codes tragenden Variable) durch `HTTP_CLIENT_ERROR_BAD_STATE` ersetzt. + **Fix vom 2026-09-12 (am EVK gefunden):** `nl_sha256_init()` stand am Anfang von `fwup_scheduler()`, + also einmal beim Task-Start. Der Task überlebt aber jede Update-Sitzung, sodass ab dem zweiten Versuch + pro Boot ein bereits finalisierter Kontext weiterbenutzt wurde und der Trailer-Hash zwangsläufig nicht + mehr passte (`last_ota_error=hash`). Der Init sitzt jetzt dort, wo der `T_BOOTER`-Header eintrifft, also + genau einmal pro Image. Ohne diesen Fix war nach jeder Ablehnung ein Reboot nötig, bevor ein Update + überhaupt wieder gelingen konnte. + 2. `Src/OS/RTOS/include/FreeRTOSConfig.h`: `configGENERATE_RUN_TIME_STATS 0`, QConnex-Debug-Hooks entfernt. 3. `undefined reference` beim Linken auf `EarlyInit` und `pre_gpio_config` (von `sdk/Platform/Sys/wm_main.c` als `extern`-Hooks erwartet, aber nur von der App bereitgestellt): diff --git a/sdk/Platform/Common/fwup/wm_fwup.c b/sdk/Platform/Common/fwup/wm_fwup.c index de54dc9..f876dba 100644 --- a/sdk/Platform/Common/fwup/wm_fwup.c +++ b/sdk/Platform/Common/fwup/wm_fwup.c @@ -1,1032 +1,1036 @@ -/***************************************************************************** -* -* 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) - { - /* 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; - } -} - +/***************************************************************************** +* +* 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; + + /* 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; + } +} +