blob: 67e15a889b326206fd7d16df75ed2e38e81a51bb [file] [log] [blame]
/*****************************************************************************
* Copyright Statement:
* --------------------
* This software is protected by Copyright and the information contained
* herein is confidential. The software may not be copied and the information
* contained herein may not be used or disclosed except with the written
* permission of MediaTek Inc. (C) 2018
*
* BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
* THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
* RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
* AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
* NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
* SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
* SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
* THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
* NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
* SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
*
* BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
* LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
* AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
* OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
* MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
*
* THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
* WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
* LAWS PRINCIPLES. ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
* RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
* THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
*
*****************************************************************************/
/*******************************************************************************
* Filename:
* ---------
* mcf_util.c
*
* Project:
* --------
* UMOLYA
*
* Description:
* ------------
* MD Configuration Framework internal utility.
*
* Author:
* -------
* -------
*
*==============================================================================
* HISTORY
* Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
*------------------------------------------------------------------------------
* removed!
*
* removed!
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
*
* removed!
* removed!
*
* removed!
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
*
* removed!
*
* removed!
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
*
* removed!
* removed!
*
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
*
*------------------------------------------------------------------------------
* Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
*==============================================================================
*******************************************************************************/
#include "kal_public_api.h"
#include "fs_general_api.h"
#include "mcf_custom.h"
#include "mcf_defs.h"
#include "mcf_debug.h"
#include "mcf_struct.h"
#include "mcf_util.h"
#include "mcf_object.h"
#include "cust_chl_interface.h"
#include "us_timer.h"
#include <stdarg.h>
#include "sleepdrv_interface.h"
/*------------------------------------------------------------------------------
* Global variables.
*----------------------------------------------------------------------------*/
mcf_t mcf_inst_g;
kal_enhmutexid mcf_enhmutex_g = NULL;
event_scheduler *mcf_timer_es_g = NULL;
eventid mcf_timer_eventid_g = NULL;
mcf_common_t com_Mcf;
kal_enhmutexid mcf_utfwk_enhmutex_g = NULL;
mcf_file_info_t new_file_info;
mcf_file_info_t old_file_info;
#undef BOOT_TRC_MSG
#define BOOT_TRC_MSG(_name,_format) {_format},
static MCF_BOOT_LOG boot_trace_format[] =
{
#include "mcf_boot_trace.h"
};
/*------------------------------------------------------------------------------
* Helper macro.
*----------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------
* Private data structure.
*----------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------
* Private variables.
*----------------------------------------------------------------------------*/
static KAL_ADM_ID mcf_mem_id = NULL;
static kal_uint8 mcf_mem_pool[MCF_MAX_MEM_MALLOC_SIZE];
static kal_bool mcf_mem_init_flag = KAL_FALSE;
/*------------------------------------------------------------------------------
* Private fucntions.
*----------------------------------------------------------------------------*/
extern kal_char* release_verno(void);
extern kal_char* build_date_time(void);
/*------------------------------------------------------------------------------
* Public fucntions.
*----------------------------------------------------------------------------*/
#if !defined(__HIF_CCCI_SUPPORT__) || !defined(__MTK_TARGET__)
kal_int32 MCF_dummy_FS_CMPT_Read(const WCHAR * FileName, NVRAM_FS_PARAM_CMPT_T* nvram_param)
{
return FS_NO_ERROR;
}
#include <stdio.h>
#include <windows.h>
kal_int32 MCF_Win_FS_CMPT_Read(const WCHAR * FileName, NVRAM_FS_PARAM_CMPT_T* nvram_param)
{
char fname[MCF_FILE_MAX_NAME_LEN] = { 0 };
char fullpath[MCF_FILE_MAX_MD_PATH_LEN + MCF_FILE_MAX_NAME_LEN] = { 0 };
kal_uint32 i = 0;
FILE *fd = NULL;
if (mcf_utfwk_is_working_status == KAL_TRUE){
return FS_NO_ERROR;
}
// translate wchar to char
WCHAR *ptr = FileName; // skip drive "S:"
while (*ptr != NULL) {
fname[i++] = (char)*ptr;
ptr++;
}
if (GetModuleFileName(NULL, fullpath, MCF_FILE_MAX_MD_PATH_LEN + MCF_FILE_MAX_NAME_LEN) != NULL) {
char *pch = strrchr(fullpath, '\\');
*(++pch) = 0;
strncat(fullpath, fname, MCF_FILE_MAX_MD_PATH_LEN + MCF_FILE_MAX_NAME_LEN - 1);
}
else {
return FS_FILE_NOT_FOUND;
}
// due to open & close operation are must, so always open & close file (ignore CCCI_FS_CMPT_OPEN & CCCI_FS_CMPT_CLOSE)
fd = fopen(fullpath, "rb");
if (fd == NULL)
return FS_FILE_NOT_FOUND;
//get file size
if (nvram_param->opid_map & CCCI_FS_CMPT_GETFILESIZE)
{
fseek(fd, 0, SEEK_END);
*nvram_param->FileSize = ftell(fd);
fseek(fd, 0, SEEK_SET);
}
// seek
if (nvram_param->opid_map & CCCI_FS_CMPT_SEEK)
{
fseek(fd, nvram_param->Offset, nvram_param->Whence);
}
// read
if (nvram_param->opid_map & CCCI_FS_CMPT_READ)
{
if (nvram_param->DataPtr != NULL) {
*nvram_param->Read = fread(nvram_param->DataPtr, nvram_param->Length, 1, fd);
}
}
fclose(fd);
return FS_NO_ERROR;
}
#endif
void mcf_mem_init(void)
{
if (mcf_mem_init_flag == KAL_FALSE)
{
mcf_mem_id = kal_adm_create((void*)mcf_mem_pool, sizeof(mcf_mem_pool), NULL, KAL_FALSE);
mcf_mem_init_flag = KAL_TRUE;
}
}
void *mcf_malloc(unsigned int size)
{
mcf_mem_init();
if (NULL != mcf_mem_id) {
void *ret = kal_adm_alloc(mcf_mem_id, size);
if(ret == NULL)
{
MCF_BOOT_TRACE(MCF_BOOT_TR_ALLOC_MEM_ERROR);
MD_TRC_MCF_TR_ALLOC_MEM_ERROR();
}
return ret;
}
return NULL;
}
void mcf_free(void *ptr)
{
if (NULL == mcf_mem_id) {
return;
}
kal_adm_free(mcf_mem_id, ptr);
}
void mcf_create_custom_folder(mcf_t *pMcf)
{
kal_wchar foldername[MCF_FILE_MAX_MD_PATH_LEN] = {0};
kal_int32 fs_api_ret;
kal_wsprintf(foldername, "%s\0", MCF_FS_CUSTOM_FOLDER_PATH);
fs_api_ret = FS_CreateDir(foldername);
if (fs_api_ret < FS_NO_ERROR) {
com_Mcf.boot_trace_flag |= MCF_BOOT_TRACE_F_CREATE_CUSTOM_FOLDER_FAIL;
MCF_BOOT_TRACE(MCF_BOOT_TR_CREATE_CUSTOM_FOLDER_FAIL, MCF_FS_CUSTOM_FOLDER_PATH, fs_api_ret);
}
return;
}
mcf_ota_result_e mcf_read_ota_file(
kal_bool is_booting,
kal_char *req_fs_root_path,
kal_char *req_file_path_name,
l4c_mcf_path_type_enum *apply_path_type,
kal_char *apply_filename,
mcf_t *pMcf)
{
NVRAM_FS_PARAM_CMPT_T fs_cmpt;
FS_FileDetail fs_file_detail[L4C_MCF_PATH_TYPE_MAX] = {0};
kal_uint32 read_byte = 0;
kal_uint32 file_size = 0;
mcf_ota_result_e ret = MCF_OTA_R_SUCCESS;
mcf_ota_file_t *ota_file = &(pMcf->ota_file);
kal_wchar filename[MCF_FILE_MAX_MD_PATH_LEN + MCF_FILE_MAX_NAME_LEN];
mcf_tool_file_info_t *pFile;
kal_char password[MCF_MAX_PASSWORD_LEN] = {0};
kal_bool is_get_custom_filename = KAL_FALSE;
kal_bool is_default_path;
kal_uint32 dummy_para;
kal_int32 fs_api_ret[L4C_MCF_PATH_TYPE_MAX];
kal_uint64 last_mod_time = 0;
kal_char default_file_name_tag[30];
kal_uint64 ini_path_ota_file_last_mod_time = 0;
kal_uint64 ini_path_runtime_file_last_mod_time = 0;
kal_char ini_root_path[20];
fs_cmpt.opid_map = NVRAM_FS_CMPT_OPEN | NVRAM_FS_CMPT_GETFILESIZE | NVRAM_FS_CMPT_CLOSE;
fs_cmpt.Flag = FS_READ_ONLY;
fs_cmpt.Length = 0;
fs_cmpt.Offset = 0;
fs_cmpt.Whence = FS_FILE_BEGIN;
fs_cmpt.DataPtr = &dummy_para;
fs_cmpt.Read = &dummy_para;
fs_cmpt.FileSize = &file_size;
if ( (strcmp(req_fs_root_path, "") != 0) && (strcmp(req_file_path_name, "") != 0) ) {
if (strcmp(req_fs_root_path, MCF_FS_DEFAULT_FOLDER_PATH) == 0) {
*apply_path_type = L4C_MCF_PATH_TYPE_OTA;
} else if (strcmp(req_fs_root_path, MCF_FS_CUSTOM_FOLDER_PATH) == 0) {
*apply_path_type = L4C_MCF_PATH_TYPE_RUNTIME;
}else{
MD_TRC_MCF_TR_READ_OTA_FILE_INVALID_PATH(req_fs_root_path);
ret = MCF_OTA_R_INVALID_PARAMETER;
return ret;
}
kal_wsprintf(filename, "%s\\%s\0", req_fs_root_path, req_file_path_name);
strncpy(apply_filename, req_file_path_name, MCF_FILE_MAX_NAME_LEN - 1);
is_default_path = KAL_FALSE;
} else {
is_get_custom_filename = mcf_get_custom_file_path_name((kal_uint8 *)apply_path_type, apply_filename);
strncpy(default_file_name_tag, "Default_OTA_File_Name", 29);
if (is_get_custom_filename == KAL_TRUE) {
if (*apply_path_type >= L4C_MCF_PATH_TYPE_MAX || *apply_path_type < 0) {
MD_TRC_MCF_TR_READ_OTA_FILE_INVALID_PATH_TYPE(*apply_path_type);
ret = MCF_OTA_R_INVALID_PARAMETER;
return ret;
}
if (*apply_path_type == L4C_MCF_PATH_TYPE_OTA) {
kal_wsprintf(filename, "%s\\%s\0", MCF_FS_DEFAULT_FOLDER_PATH, apply_filename);
} else if (*apply_path_type == L4C_MCF_PATH_TYPE_RUNTIME) {
kal_wsprintf(filename, "%s\\%s\0", MCF_FS_CUSTOM_FOLDER_PATH, apply_filename);
}
}
else {
/* Try to read default ota file name in INI file */
/* Compare modified time of ini file to select which file to be applied */
if(mcf_get_file_last_mod_time (MCF_FS_DEFAULT_INI_FILE_NAME, L4C_MCF_PATH_TYPE_OTA, &ini_path_ota_file_last_mod_time) == MCF_OTA_R_READ_OTA_FILE_FAIL){
ini_path_ota_file_last_mod_time = 0;
MD_TRC_MCF_TR_READ_OTA_FILE_READ_INI_FILE_FAIL(L4C_MCF_PATH_TYPE_OTA, MCF_OTA_R_READ_OTA_FILE_FAIL);
if (mcf_get_file_last_mod_time (MCF_FS_DEFAULT_INI_FILE_NAME, L4C_MCF_PATH_TYPE_RUNTIME, &ini_path_runtime_file_last_mod_time) == MCF_OTA_R_READ_OTA_FILE_FAIL){
ini_path_runtime_file_last_mod_time = 0;
MD_TRC_MCF_TR_READ_OTA_FILE_READ_INI_FILE_FAIL(L4C_MCF_PATH_TYPE_RUNTIME, MCF_OTA_R_READ_OTA_FILE_FAIL);
}
}
if(mcf_get_file_last_mod_time (MCF_FS_DEFAULT_INI_FILE_NAME, L4C_MCF_PATH_TYPE_RUNTIME, &ini_path_runtime_file_last_mod_time) == MCF_OTA_R_READ_OTA_FILE_FAIL){
ini_path_runtime_file_last_mod_time = 0;
MD_TRC_MCF_TR_READ_OTA_FILE_READ_INI_FILE_FAIL(L4C_MCF_PATH_TYPE_RUNTIME, MCF_OTA_R_READ_OTA_FILE_FAIL);
if(mcf_get_file_last_mod_time (MCF_FS_DEFAULT_INI_FILE_NAME, L4C_MCF_PATH_TYPE_OTA, &ini_path_ota_file_last_mod_time) == MCF_OTA_R_READ_OTA_FILE_FAIL){
ini_path_ota_file_last_mod_time = 0;
MD_TRC_MCF_TR_READ_OTA_FILE_READ_INI_FILE_FAIL(L4C_MCF_PATH_TYPE_OTA, MCF_OTA_R_READ_OTA_FILE_FAIL);
}
}
kal_mem_set(ini_root_path,0,20);
if (ini_path_ota_file_last_mod_time > ini_path_runtime_file_last_mod_time){
strncpy(ini_root_path,MCF_FS_DEFAULT_FOLDER_PATH, 19);
}else{
strncpy(ini_root_path,MCF_FS_CUSTOM_FOLDER_PATH, 19);
}
if (mcf_read_ini_file(ini_root_path , MCF_FS_DEFAULT_INI_FILE_NAME, apply_path_type, apply_filename, pMcf) == MCF_OTA_R_SUCCESS &&
mcf_find_ini_item((kal_char *)pMcf->ini_file.buff, default_file_name_tag, apply_filename, pMcf) == KAL_TRUE && strcmp(apply_filename, "") != 0) {
strncat (apply_filename,".mcfota", MCF_FILE_MAX_NAME_LEN - 1);
kal_wsprintf(filename, "%s\\%s\0", MCF_FS_DEFAULT_FOLDER_PATH, apply_filename);
MCF_BOOT_TRACE(MCF_BOOT_TR_DO_OTA_FULL_GET_DEFAULT_OTA_FILE_NAME_FROM_INI, apply_filename);
}else{
kal_wsprintf(filename, "%s\\%s\0", MCF_FS_DEFAULT_FOLDER_PATH, MCF_FS_DEFAULT_OTA_FILE_NAME);
strncpy(apply_filename, MCF_FS_DEFAULT_OTA_FILE_NAME, MCF_FILE_MAX_NAME_LEN - 1);
}
/* Compare modified time of OTA file to select which file to be applied */
fs_api_ret[L4C_MCF_PATH_TYPE_OTA] = FS_GetFileDetail(filename, &fs_file_detail[L4C_MCF_PATH_TYPE_OTA]);
MD_TRC_MCF_TR_READ_OTA_FILE_MODIFIED_TIME(L4C_MCF_PATH_TYPE_OTA, fs_api_ret[L4C_MCF_PATH_TYPE_OTA],
(kal_uint32)((fs_file_detail[L4C_MCF_PATH_TYPE_OTA].LastStatusChangeTime >> 32) & 0xFFFFFFFF), (kal_uint32)(fs_file_detail[L4C_MCF_PATH_TYPE_OTA].LastStatusChangeTime & 0xFFFFFFFF));
if (fs_api_ret[L4C_MCF_PATH_TYPE_OTA] != FS_NO_ERROR) {
kal_mem_set(&fs_file_detail[L4C_MCF_PATH_TYPE_OTA], 0, sizeof(FS_FileDetail));
}
kal_wsprintf(filename, "%s\\%s\0", MCF_FS_CUSTOM_FOLDER_PATH, MCF_FS_DEFAULT_OTA_FILE_NAME);
fs_api_ret[L4C_MCF_PATH_TYPE_RUNTIME] = FS_GetFileDetail(filename, &fs_file_detail[L4C_MCF_PATH_TYPE_RUNTIME]);
MD_TRC_MCF_TR_READ_OTA_FILE_MODIFIED_TIME(L4C_MCF_PATH_TYPE_RUNTIME, fs_api_ret[L4C_MCF_PATH_TYPE_RUNTIME],
(kal_uint32)((fs_file_detail[L4C_MCF_PATH_TYPE_RUNTIME].LastStatusChangeTime >> 32) & 0xFFFFFFFF), (kal_uint32)(fs_file_detail[L4C_MCF_PATH_TYPE_RUNTIME].LastStatusChangeTime & 0xFFFFFFFF));
if (fs_api_ret[L4C_MCF_PATH_TYPE_RUNTIME] != FS_NO_ERROR) {
kal_mem_set(&fs_file_detail[L4C_MCF_PATH_TYPE_RUNTIME], 0, sizeof(FS_FileDetail));
}
if ( (fs_api_ret[L4C_MCF_PATH_TYPE_OTA] == FS_NO_ERROR) || (fs_api_ret[L4C_MCF_PATH_TYPE_RUNTIME] == FS_NO_ERROR) ) {
if (fs_file_detail[L4C_MCF_PATH_TYPE_OTA].LastStatusChangeTime > fs_file_detail[L4C_MCF_PATH_TYPE_RUNTIME].LastStatusChangeTime) {
*apply_path_type = L4C_MCF_PATH_TYPE_OTA;
kal_wsprintf(filename, "%s\\%s\0", MCF_FS_DEFAULT_FOLDER_PATH, apply_filename);
} else {
*apply_path_type = L4C_MCF_PATH_TYPE_RUNTIME;
kal_wsprintf(filename, "%s\\%s\0", MCF_FS_CUSTOM_FOLDER_PATH, MCF_FS_DEFAULT_OTA_FILE_NAME);
}
} else {
if (is_booting == KAL_TRUE) {
com_Mcf.boot_trace_flag |= MCF_BOOT_TRACE_F_READ_OTA_FILE_FAIL;
MCF_BOOT_TRACE(MCF_BOOT_TR_READ_OTA_FILE_COMPARE_FAIL);
}
MD_TRC_MCF_TR_READ_OTA_FILE_COMPARE_FAIL();
ret = MCF_OTA_R_READ_OTA_FILE_FAIL;
return ret;
}
}
is_default_path = KAL_TRUE;
}
fs_api_ret[0] = MCF_FS_CMPT_Read(filename, &fs_cmpt);
if (fs_api_ret[0] < FS_NO_ERROR) {
if (is_booting == KAL_TRUE) {
MCF_BOOT_TRACE(MCF_BOOT_TR_READ_OTA_FILE_FAIL, *apply_path_type, fs_api_ret[0]);
MCF_BOOT_TRACE(MCF_BOOT_TR_STRING, apply_filename);
}
MD_TRC_MCF_TR_READ_OTA_FILE_FAIL(*apply_path_type, fs_api_ret[0]);
dhl_print_string(TRACE_INFO, DHL_USER_FLAG_NONE, MOD_MCF, apply_filename);
/* If cannot read given OTA file, read default OTA file */
if (is_default_path == KAL_FALSE) {
is_get_custom_filename = mcf_get_custom_file_path_name((kal_uint8 *)apply_path_type, apply_filename);
if (*apply_path_type >= L4C_MCF_PATH_TYPE_MAX || *apply_path_type < 0) {
MD_TRC_MCF_TR_READ_OTA_FILE_INVALID_PATH_TYPE(*apply_path_type);
ret = MCF_OTA_R_INVALID_PARAMETER;
return ret;
}
if (is_get_custom_filename == KAL_TRUE) {
if (*apply_path_type == L4C_MCF_PATH_TYPE_OTA) {
kal_wsprintf(filename, "%s\\%s\0", MCF_FS_DEFAULT_FOLDER_PATH, apply_filename);
} else if (*apply_path_type == L4C_MCF_PATH_TYPE_RUNTIME) {
kal_wsprintf(filename, "%s\\%s\0", MCF_FS_CUSTOM_FOLDER_PATH, apply_filename);
}
} else {
/* Compare modified time of OTA file to select which file to be applied */
kal_wsprintf(filename, "%s\\%s\0", MCF_FS_DEFAULT_FOLDER_PATH, MCF_FS_DEFAULT_OTA_FILE_NAME);
fs_api_ret[L4C_MCF_PATH_TYPE_OTA] = FS_GetFileDetail(filename, &fs_file_detail[L4C_MCF_PATH_TYPE_OTA]);
MD_TRC_MCF_TR_READ_OTA_FILE_MODIFIED_TIME(L4C_MCF_PATH_TYPE_OTA, fs_api_ret[L4C_MCF_PATH_TYPE_OTA],
(kal_uint32)((fs_file_detail[L4C_MCF_PATH_TYPE_OTA].LastStatusChangeTime >> 32) & 0xFFFFFFFF), (kal_uint32)(fs_file_detail[L4C_MCF_PATH_TYPE_OTA].LastStatusChangeTime & 0xFFFFFFFF));
if (fs_api_ret[L4C_MCF_PATH_TYPE_OTA] != FS_NO_ERROR) {
kal_mem_set(&fs_file_detail[L4C_MCF_PATH_TYPE_OTA], 0, sizeof(FS_FileDetail));
}
kal_wsprintf(filename, "%s\\%s\0", MCF_FS_CUSTOM_FOLDER_PATH, MCF_FS_DEFAULT_OTA_FILE_NAME);
fs_api_ret[L4C_MCF_PATH_TYPE_RUNTIME] = FS_GetFileDetail(filename, &fs_file_detail[L4C_MCF_PATH_TYPE_RUNTIME]);
MD_TRC_MCF_TR_READ_OTA_FILE_MODIFIED_TIME(L4C_MCF_PATH_TYPE_RUNTIME, fs_api_ret[L4C_MCF_PATH_TYPE_RUNTIME],
(kal_uint32)((fs_file_detail[L4C_MCF_PATH_TYPE_RUNTIME].LastStatusChangeTime >> 32) & 0xFFFFFFFF), (kal_uint32)(fs_file_detail[L4C_MCF_PATH_TYPE_RUNTIME].LastStatusChangeTime & 0xFFFFFFFF));
if (fs_api_ret[L4C_MCF_PATH_TYPE_RUNTIME] != FS_NO_ERROR) {
kal_mem_set(&fs_file_detail[L4C_MCF_PATH_TYPE_RUNTIME], 0, sizeof(FS_FileDetail));
}
if ( (fs_api_ret[L4C_MCF_PATH_TYPE_OTA] == FS_NO_ERROR) || (fs_api_ret[L4C_MCF_PATH_TYPE_RUNTIME] == FS_NO_ERROR) ) {
if (fs_file_detail[L4C_MCF_PATH_TYPE_OTA].LastStatusChangeTime > fs_file_detail[L4C_MCF_PATH_TYPE_RUNTIME].LastStatusChangeTime) {
*apply_path_type = L4C_MCF_PATH_TYPE_OTA;
kal_wsprintf(filename, "%s\\%s\0", MCF_FS_DEFAULT_FOLDER_PATH, MCF_FS_DEFAULT_OTA_FILE_NAME);
} else {
*apply_path_type = L4C_MCF_PATH_TYPE_RUNTIME;
kal_wsprintf(filename, "%s\\%s\0", MCF_FS_CUSTOM_FOLDER_PATH, MCF_FS_DEFAULT_OTA_FILE_NAME);
}
} else {
if (is_booting == KAL_TRUE) {
com_Mcf.boot_trace_flag |= MCF_BOOT_TRACE_F_READ_OTA_FILE_FAIL;
MCF_BOOT_TRACE(MCF_BOOT_TR_READ_OTA_FILE_COMPARE_FAIL);
}
MD_TRC_MCF_TR_READ_OTA_FILE_COMPARE_FAIL();
ret = MCF_OTA_R_READ_OTA_FILE_FAIL;
return ret;
}
strncpy(apply_filename, MCF_FS_DEFAULT_OTA_FILE_NAME, MCF_FILE_MAX_NAME_LEN - 1);
}
fs_api_ret[0] = MCF_FS_CMPT_Read(filename, &fs_cmpt);
if (fs_api_ret[0] < FS_NO_ERROR) {
if (is_booting == KAL_TRUE) {
com_Mcf.boot_trace_flag |= MCF_BOOT_TRACE_F_READ_OTA_FILE_FAIL;
MCF_BOOT_TRACE(MCF_BOOT_TR_READ_OTA_FILE_FAIL, *apply_path_type, fs_api_ret[0]);
MCF_BOOT_TRACE(MCF_BOOT_TR_STRING, apply_filename);
}
MD_TRC_MCF_TR_READ_OTA_FILE_FAIL(*apply_path_type, fs_api_ret[0]);
dhl_print_string(TRACE_INFO, DHL_USER_FLAG_NONE, MOD_MCF, apply_filename);
ret = MCF_OTA_R_READ_OTA_FILE_FAIL;
return ret;
}
} else {
ret = MCF_OTA_R_READ_OTA_FILE_FAIL;
return ret;
}
}
if (file_size > MCF_MAX_OTA_FILE_SIZE) {
if (is_booting == KAL_TRUE) {
com_Mcf.boot_trace_flag |= MCF_BOOT_TRACE_F_OTA_FILE_OVERSIZE;
MCF_BOOT_TRACE(MCF_BOOT_TR_READ_OTA_FILE_OVERSIZE, file_size, MCF_MAX_OTA_FILE_SIZE);
}
MD_TRC_MCF_TR_READ_OTA_FILE_OVERSIZE(file_size, MCF_MAX_OTA_FILE_SIZE);
ret = MCF_OTA_R_READ_OTA_FILE_FAIL;
return ret;
}
/* Read file */
fs_cmpt.opid_map = NVRAM_FS_CMPT_OPEN | NVRAM_FS_CMPT_READ | NVRAM_FS_CMPT_CLOSE;
fs_cmpt.Flag = FS_READ_ONLY;
fs_cmpt.Length = file_size;
fs_cmpt.Offset = 0;
fs_cmpt.Whence = FS_FILE_BEGIN;
fs_cmpt.DataPtr = ota_file->buff;
fs_cmpt.Read = &read_byte;
fs_cmpt.FileSize = &dummy_para;
fs_api_ret[*apply_path_type] = FS_GetFileDetail(filename, &fs_file_detail[*apply_path_type]);
MD_TRC_MCF_TR_READ_OTA_FILE_MODIFIED_TIME(*apply_path_type, fs_api_ret[*apply_path_type],
(kal_uint32)((fs_file_detail[*apply_path_type].LastStatusChangeTime >> 32) & 0xFFFFFFFF), (kal_uint32)(fs_file_detail[*apply_path_type].LastStatusChangeTime & 0xFFFFFFFF));
if (fs_api_ret[*apply_path_type] == FS_NO_ERROR) {
last_mod_time = fs_file_detail[*apply_path_type].LastStatusChangeTime;
} else {
if (is_booting == KAL_TRUE) {
com_Mcf.boot_trace_flag |= MCF_BOOT_TRACE_F_READ_OTA_FILE_FAIL;
MCF_BOOT_TRACE(MCF_BOOT_TR_READ_OTA_FILE_FAIL, *apply_path_type, fs_api_ret[*apply_path_type]);
MCF_BOOT_TRACE(MCF_BOOT_TR_STRING, apply_filename);
}
MD_TRC_MCF_TR_READ_OTA_FILE_FAIL(*apply_path_type, fs_api_ret[*apply_path_type]);
dhl_print_string(TRACE_INFO, DHL_USER_FLAG_NONE, MOD_MCF, apply_filename);
ret = MCF_OTA_R_READ_OTA_FILE_FAIL;
return ret;
}
MCF_W_LOCK_OBJECT(ota_file, mcf_enhmutex_g);
if (ota_file) {
fs_api_ret[0] = MCF_FS_CMPT_Read(filename, &fs_cmpt);
if (fs_api_ret[0] < FS_NO_ERROR) {
MCF_W_UNLOCK_OBJECT(ota_file, mcf_enhmutex_g);
if (is_booting == KAL_TRUE) {
com_Mcf.boot_trace_flag |= MCF_BOOT_TRACE_F_READ_OTA_FILE_FAIL;
MCF_BOOT_TRACE(MCF_BOOT_TR_READ_OTA_FILE_FAIL, *apply_path_type, fs_api_ret[0]);
MCF_BOOT_TRACE(MCF_BOOT_TR_STRING, apply_filename);
}
MD_TRC_MCF_TR_READ_OTA_FILE_FAIL(*apply_path_type, fs_api_ret[0]);
dhl_print_string(TRACE_INFO, DHL_USER_FLAG_NONE, MOD_MCF, apply_filename);
ret = MCF_OTA_R_READ_OTA_FILE_FAIL;
return ret;
}
pFile = (mcf_tool_file_info_t *)(ota_file->buff);
#ifdef __MCF_FIND_TAG_SUPPORT__
if (pFile->file_version == 2 || pFile->file_version == 3) {
#else
if (pFile->file_version == 3) {
#endif
kal_uint32 operation_mask = 0;
/* Check custom operation mask */
operation_mask = mcf_get_custom_operation_mask();
if ((pFile->operation_mask & operation_mask) != operation_mask) {
if (is_booting == KAL_TRUE) {
com_Mcf.boot_trace_flag |= MCF_BOOT_TRACE_F_OPERATION_MASK_FAIL;
MCF_BOOT_TRACE(MCF_BOOT_TR_READ_OTA_FILE_OPERATION_MASK_FAIL, apply_filename, pFile->operation_mask, operation_mask);
}
MD_TRC_MCF_TR_READ_OTA_FILE_OPERATION_MASK_FAIL(apply_filename, pFile->operation_mask, operation_mask);
ret = MCF_OTA_R_INVALID_FILE;
kal_mem_set(ota_file->buff, 0, MCF_MAX_OTA_FILE_SIZE);
kal_mem_set(ota_file->relative_path_name, 0, MCF_FILE_MAX_NAME_LEN);
ota_file->path_type = 0;
ota_file->last_mod_time = 0;
MCF_W_UNLOCK_OBJECT(ota_file, mcf_enhmutex_g);
return ret;
}
/* First check digest first
* If file is encrypted and has checksum.
* Decrypt file before checking checksum.
*/
// RSA verify digest
if ((pFile->operation_mask & MCF_FILE_OP_SHA256_RSA2048) != 0) {
if (mcf_verify_digest(MCF_FILE_OP_SHA256_RSA2048, (mcf_tool_file_info_t *)(ota_file->buff), (mcf_digest *)(ota_file->buff + pFile->file_size)) != KAL_TRUE) {
kal_mem_set(ota_file->buff, 0, MCF_MAX_OTA_FILE_SIZE);
kal_mem_set(ota_file->relative_path_name, 0, MCF_FILE_MAX_NAME_LEN);
ota_file->path_type = 0;
ota_file->last_mod_time = 0;
MCF_W_UNLOCK_OBJECT(ota_file, mcf_enhmutex_g);
if (is_booting == KAL_TRUE) {
com_Mcf.boot_trace_flag |= MCF_BOOT_TRACE_F_DIGEST_FAIL;
MCF_BOOT_TRACE(MCF_BOOT_TR_READ_OTA_FILE_DIGEST_FAIL, apply_filename);
}
MD_TRC_MCF_TR_READ_OTA_FILE_DIGEST_FAIL(apply_filename);
ret = MCF_OTA_R_DIGEST_FAIL;
return ret;
}
}
else if ((pFile->operation_mask & MCF_FILE_OP_SHA384_RSA3072) != 0) {
if (mcf_verify_digest(MCF_FILE_OP_SHA384_RSA3072, (mcf_tool_file_info_t *)(ota_file->buff), (mcf_digest *)(ota_file->buff + pFile->file_size)) != KAL_TRUE) {
kal_mem_set(ota_file->buff, 0, MCF_MAX_OTA_FILE_SIZE);
kal_mem_set(ota_file->relative_path_name, 0, MCF_FILE_MAX_NAME_LEN);
ota_file->path_type = 0;
ota_file->last_mod_time = 0;
MCF_W_UNLOCK_OBJECT(ota_file, mcf_enhmutex_g);
if (is_booting == KAL_TRUE) {
com_Mcf.boot_trace_flag |= MCF_BOOT_TRACE_F_DIGEST_FAIL;
MCF_BOOT_TRACE(MCF_BOOT_TR_READ_OTA_FILE_DIGEST_FAIL, apply_filename);
}
MD_TRC_MCF_TR_READ_OTA_FILE_DIGEST_FAIL(apply_filename);
ret = MCF_OTA_R_DIGEST_FAIL;
return ret;
}
}
if ( (pFile->operation_mask & MCF_FILE_OP_AES_128) != 0) {
mcf_get_custom_aes_password(password);
if (mcf_decrypt_128bit(password, (kal_char *)(ota_file->buff + pFile->total_len), (pFile->file_size - pFile->total_len) ) != KAL_TRUE) {
kal_mem_set(ota_file->buff, 0, MCF_MAX_OTA_FILE_SIZE);
kal_mem_set(ota_file->relative_path_name, 0, MCF_FILE_MAX_NAME_LEN);
ota_file->path_type = 0;
ota_file->last_mod_time = 0;
MCF_W_UNLOCK_OBJECT(ota_file, mcf_enhmutex_g);
if (is_booting == KAL_TRUE) {
com_Mcf.boot_trace_flag |= MCF_BOOT_TRACE_F_DECRYPTION_FAIL;
MCF_BOOT_TRACE(MCF_BOOT_TR_READ_OTA_FILE_DECRYPTION_FAIL, apply_filename);
}
MD_TRC_MCF_TR_READ_OTA_FILE_DECRYPTION_FAIL(apply_filename);
ret = MCF_OTA_R_DECRYPTION_FAIL;
return ret;
}
}
// for AES_256
else if ((pFile->operation_mask & MCF_FILE_OP_AES_256) != 0) {
mcf_get_custom_aes_password(password);
if (mcf_decrypt_256bit(password, (kal_char *)(ota_file->buff + pFile->total_len), (pFile->file_size - pFile->total_len)) != KAL_TRUE) {
kal_mem_set(ota_file->buff, 0, MCF_MAX_OTA_FILE_SIZE);
kal_mem_set(ota_file->relative_path_name, 0, MCF_FILE_MAX_NAME_LEN);
ota_file->path_type = 0;
ota_file->last_mod_time = 0;
MCF_W_UNLOCK_OBJECT(ota_file, mcf_enhmutex_g);
if (is_booting == KAL_TRUE) {
com_Mcf.boot_trace_flag |= MCF_BOOT_TRACE_F_DECRYPTION_FAIL;
MCF_BOOT_TRACE(MCF_BOOT_TR_READ_OTA_FILE_DECRYPTION_FAIL, apply_filename);
}
MD_TRC_MCF_TR_READ_OTA_FILE_DECRYPTION_FAIL(apply_filename);
ret = MCF_OTA_R_DECRYPTION_FAIL;
return ret;
}
}
if ( (pFile->operation_mask & MCF_FILE_OP_CHECKSUM) != 0) {
if (mcf_check_check_sum((kal_uint32 *)(ota_file->buff), pFile->file_size) != 0) {
kal_mem_set(ota_file->buff, 0, MCF_MAX_OTA_FILE_SIZE);
kal_mem_set(ota_file->relative_path_name, 0, MCF_FILE_MAX_NAME_LEN);
ota_file->path_type = 0;
ota_file->last_mod_time = 0;
MCF_W_UNLOCK_OBJECT(ota_file, mcf_enhmutex_g);
if (is_booting == KAL_TRUE) {
com_Mcf.boot_trace_flag |= MCF_BOOT_TRACE_F_CHECKSUM_ERROR;
MCF_BOOT_TRACE(MCF_BOOT_TR_READ_OTA_FILE_CHECKSUM_ERROR, apply_filename);
}
MD_TRC_MCF_TR_READ_OTA_FILE_CHECKSUM_ERROR(apply_filename);
ret = MCF_OTA_R_CHECKSUM_ERROR;
return ret;
}
}
} else {
if (is_booting == KAL_TRUE) {
com_Mcf.boot_trace_flag |= MCF_BOOT_TRACE_F_INVALID_FILE;
MCF_BOOT_TRACE(MCF_BOOT_TR_READ_OTA_FILE_INVALID_FILE_VERSION, pFile->file_version);
}
MD_TRC_MCF_TR_READ_OTA_FILE_INVALID_FILE_VERSION(pFile->file_version);
kal_mem_set(ota_file->buff, 0, MCF_MAX_OTA_FILE_SIZE);
kal_mem_set(ota_file->relative_path_name, 0, MCF_FILE_MAX_NAME_LEN);
ota_file->path_type = 0;
ota_file->last_mod_time = 0;
MCF_W_UNLOCK_OBJECT(ota_file, mcf_enhmutex_g);
ret = MCF_OTA_R_INVALID_FILE;
return ret;
}
ota_file->path_type = *apply_path_type;
ota_file->last_mod_time = last_mod_time;
#if defined(__MCF_UT_FRAMEWORK_SUPPORT__)
if (strcmp(ota_file->relative_path_name, "") == 0){
strncpy(ota_file->relative_path_name, apply_filename, MCF_FILE_MAX_NAME_LEN - 1);
}else{
strncpy(apply_filename, ota_file->relative_path_name, MCF_FILE_MAX_NAME_LEN - 1);
}
#else
strncpy(ota_file->relative_path_name, apply_filename, MCF_FILE_MAX_NAME_LEN - 1);
#endif
MCF_W_UNLOCK_OBJECT(ota_file, mcf_enhmutex_g);
} else {
if (is_booting == KAL_TRUE) {
com_Mcf.boot_trace_flag |= MCF_BOOT_TRACE_F_TAKE_WRITE_LOCK_FAIL;
MCF_BOOT_TRACE(MCF_BOOT_TR_READ_OTA_FILE_TAKE_WRITE_LOCK_FAIL, apply_filename, *apply_path_type);
}
MD_TRC_MCF_TR_READ_OTA_FILE_TAKE_WRITE_LOCK_FAIL(apply_filename, *apply_path_type);
ret = MCF_OTA_R_READ_OTA_FILE_FAIL;
}
return ret;
}
mcf_ota_result_e mcf_read_tlvota_file(
kal_bool is_booting,
kal_uint8 sim_id,
kal_char *req_fs_root_path,
kal_char *req_file_path_name,
l4c_mcf_path_type_enum *apply_path_type,
kal_char *apply_filename,
mcf_t *pMcf)
{
NVRAM_FS_PARAM_CMPT_T fs_cmpt;
FS_FileDetail fs_file_detail[L4C_MCF_PATH_TYPE_MAX] = {0};
kal_uint32 read_byte = 0;
kal_uint32 file_size = 0;
mcf_ota_result_e ret = MCF_OTA_R_SUCCESS;
mcf_tlvota_file_t *tlvota_file = &(pMcf->tlvota_file[sim_id]);
kal_wchar filename[MCF_FILE_MAX_MD_PATH_LEN + MCF_FILE_MAX_NAME_LEN];
mcf_tool_file_info_t *pFile;
kal_char password[MCF_MAX_PASSWORD_LEN] = {0};
kal_bool is_default_path;
kal_uint32 dummy_para;
kal_int32 fs_api_ret[L4C_MCF_PATH_TYPE_MAX];
kal_uint64 last_mod_time = 0;
fs_cmpt.opid_map = NVRAM_FS_CMPT_OPEN | NVRAM_FS_CMPT_GETFILESIZE | NVRAM_FS_CMPT_CLOSE;
fs_cmpt.Flag = FS_READ_ONLY;
fs_cmpt.Length = 0;
fs_cmpt.Offset = 0;
fs_cmpt.Whence = FS_FILE_BEGIN;
fs_cmpt.DataPtr = &dummy_para;
fs_cmpt.Read = &dummy_para;
fs_cmpt.FileSize = &file_size;
if ( (strcmp(req_fs_root_path, "") != 0) && (strcmp(req_file_path_name, "") != 0) ) {
if (strcmp(req_fs_root_path, MCF_FS_DEFAULT_FOLDER_PATH) == 0) {
*apply_path_type = L4C_MCF_PATH_TYPE_OTA;
} else if (strcmp(req_fs_root_path, MCF_FS_CUSTOM_FOLDER_PATH) == 0) {
*apply_path_type = L4C_MCF_PATH_TYPE_RUNTIME;
} else{
MD_TRC_MCF_TR_READ_TLVOTA_FILE_INVALID_PATH(req_fs_root_path);
ret = MCF_OTA_R_INVALID_PARAMETER;
return ret;
}
kal_wsprintf(filename, "%s\\%s\0", req_fs_root_path, req_file_path_name);
strncpy(apply_filename, req_file_path_name, MCF_FILE_MAX_NAME_LEN - 1);
is_default_path = KAL_FALSE;
} else {
/* Compare modified time of OP-OTA file to select which file to be applied */
kal_wsprintf(filename, "%s\\%s\0", MCF_FS_DEFAULT_FOLDER_PATH, MCF_FS_DEFAULT_TLVOTA_FILE_NAME);
fs_api_ret[L4C_MCF_PATH_TYPE_OTA] = FS_GetFileDetail(filename, &fs_file_detail[L4C_MCF_PATH_TYPE_OTA]);
MD_TRC_MCF_TR_READ_TLVOTA_FILE_MODIFIED_TIME(L4C_MCF_PATH_TYPE_OTA, fs_api_ret[L4C_MCF_PATH_TYPE_OTA],
(kal_uint32)((fs_file_detail[L4C_MCF_PATH_TYPE_OTA].LastStatusChangeTime >> 32) & 0xFFFFFFFF), (kal_uint32)(fs_file_detail[L4C_MCF_PATH_TYPE_OTA].LastStatusChangeTime & 0xFFFFFFFF));
if (fs_api_ret[L4C_MCF_PATH_TYPE_OTA] != FS_NO_ERROR) {
kal_mem_set(&fs_file_detail[L4C_MCF_PATH_TYPE_OTA], 0, sizeof(FS_FileDetail));
}
kal_wsprintf(filename, "%s\\%s\0", MCF_FS_CUSTOM_FOLDER_PATH, MCF_FS_DEFAULT_TLVOTA_FILE_NAME);
fs_api_ret[L4C_MCF_PATH_TYPE_RUNTIME] = FS_GetFileDetail(filename, &fs_file_detail[L4C_MCF_PATH_TYPE_RUNTIME]);
MD_TRC_MCF_TR_READ_TLVOTA_FILE_MODIFIED_TIME(L4C_MCF_PATH_TYPE_RUNTIME, fs_api_ret[L4C_MCF_PATH_TYPE_RUNTIME],
(kal_uint32)((fs_file_detail[L4C_MCF_PATH_TYPE_RUNTIME].LastStatusChangeTime >> 32) & 0xFFFFFFFF), (kal_uint32)(fs_file_detail[L4C_MCF_PATH_TYPE_RUNTIME].LastStatusChangeTime & 0xFFFFFFFF));
if (fs_api_ret[L4C_MCF_PATH_TYPE_RUNTIME] != FS_NO_ERROR) {
kal_mem_set(&fs_file_detail[L4C_MCF_PATH_TYPE_RUNTIME], 0, sizeof(FS_FileDetail));
}
if ( (fs_api_ret[L4C_MCF_PATH_TYPE_OTA] == FS_NO_ERROR) || (fs_api_ret[L4C_MCF_PATH_TYPE_RUNTIME] == FS_NO_ERROR) ) {
if (fs_file_detail[L4C_MCF_PATH_TYPE_OTA].LastStatusChangeTime > fs_file_detail[L4C_MCF_PATH_TYPE_RUNTIME].LastStatusChangeTime) {
*apply_path_type = L4C_MCF_PATH_TYPE_OTA;
kal_wsprintf(filename, "%s\\%s\0", MCF_FS_DEFAULT_FOLDER_PATH, MCF_FS_DEFAULT_TLVOTA_FILE_NAME);
} else {
*apply_path_type = L4C_MCF_PATH_TYPE_RUNTIME;
kal_wsprintf(filename, "%s\\%s\0", MCF_FS_CUSTOM_FOLDER_PATH, MCF_FS_DEFAULT_TLVOTA_FILE_NAME);
}
} else {
if (is_booting == KAL_TRUE) {
com_Mcf.boot_trace_flag |= MCF_BOOT_TRACE_F_READ_OTA_FILE_FAIL;
MCF_BOOT_TRACE(MCF_BOOT_TR_READ_TLVOTA_FILE_COMPARE_FAIL);
}
MD_TRC_MCF_TR_READ_TLVOTA_FILE_COMPARE_FAIL();
ret = MCF_OTA_R_READ_OTA_FILE_FAIL;
return ret;
}
strncpy(apply_filename, MCF_FS_DEFAULT_TLVOTA_FILE_NAME, MCF_FILE_MAX_NAME_LEN - 1);
is_default_path = KAL_TRUE;
}
fs_api_ret[0] = MCF_FS_CMPT_Read(filename, &fs_cmpt);
if (fs_api_ret[0] < FS_NO_ERROR) {
if (is_booting == KAL_TRUE) {
MCF_BOOT_TRACE(MCF_BOOT_TR_READ_TLVOTA_FILE_FAIL, *apply_path_type, sim_id, fs_api_ret[0]);
MCF_BOOT_TRACE(MCF_BOOT_TR_STRING, apply_filename);
}
MD_TRC_MCF_TR_READ_TLVOTA_FILE_FAIL(*apply_path_type, sim_id, fs_api_ret[0]);
dhl_print_string(TRACE_INFO, DHL_USER_FLAG_NONE, MOD_MCF, apply_filename);
/* If cannot read given TLV-OTA file, read default TLV-OTA file */
if (is_default_path == KAL_FALSE) {
/* Compare modified time of OP-OTA file to select which file to be applied */
kal_wsprintf(filename, "%s\\%s\0", MCF_FS_DEFAULT_FOLDER_PATH, MCF_FS_DEFAULT_TLVOTA_FILE_NAME);
fs_api_ret[L4C_MCF_PATH_TYPE_OTA] = FS_GetFileDetail(filename, &fs_file_detail[L4C_MCF_PATH_TYPE_OTA]);
MD_TRC_MCF_TR_READ_TLVOTA_FILE_MODIFIED_TIME(L4C_MCF_PATH_TYPE_OTA, fs_api_ret[L4C_MCF_PATH_TYPE_OTA],
(kal_uint32)((fs_file_detail[L4C_MCF_PATH_TYPE_OTA].LastStatusChangeTime >> 32) & 0xFFFFFFFF), (kal_uint32)(fs_file_detail[L4C_MCF_PATH_TYPE_OTA].LastStatusChangeTime & 0xFFFFFFFF));
if (fs_api_ret[L4C_MCF_PATH_TYPE_OTA] != FS_NO_ERROR) {
kal_mem_set(&fs_file_detail[L4C_MCF_PATH_TYPE_OTA], 0, sizeof(FS_FileDetail));
}
kal_wsprintf(filename, "%s\\%s\0", MCF_FS_CUSTOM_FOLDER_PATH, MCF_FS_DEFAULT_TLVOTA_FILE_NAME);
fs_api_ret[L4C_MCF_PATH_TYPE_RUNTIME] = FS_GetFileDetail(filename, &fs_file_detail[L4C_MCF_PATH_TYPE_RUNTIME]);
MD_TRC_MCF_TR_READ_TLVOTA_FILE_MODIFIED_TIME(L4C_MCF_PATH_TYPE_RUNTIME, fs_api_ret[L4C_MCF_PATH_TYPE_RUNTIME],
(kal_uint32)((fs_file_detail[L4C_MCF_PATH_TYPE_RUNTIME].LastStatusChangeTime >> 32) & 0xFFFFFFFF), (kal_uint32)(fs_file_detail[L4C_MCF_PATH_TYPE_RUNTIME].LastStatusChangeTime & 0xFFFFFFFF));
if (fs_api_ret[L4C_MCF_PATH_TYPE_RUNTIME] != FS_NO_ERROR) {
kal_mem_set(&fs_file_detail[L4C_MCF_PATH_TYPE_RUNTIME], 0, sizeof(FS_FileDetail));
}
if ( (fs_api_ret[L4C_MCF_PATH_TYPE_OTA] == FS_NO_ERROR) || (fs_api_ret[L4C_MCF_PATH_TYPE_RUNTIME] == FS_NO_ERROR) ) {
if (fs_file_detail[L4C_MCF_PATH_TYPE_OTA].LastStatusChangeTime > fs_file_detail[L4C_MCF_PATH_TYPE_RUNTIME].LastStatusChangeTime) {
*apply_path_type = L4C_MCF_PATH_TYPE_OTA;
kal_wsprintf(filename, "%s\\%s\0", MCF_FS_DEFAULT_FOLDER_PATH, MCF_FS_DEFAULT_TLVOTA_FILE_NAME);
} else {
*apply_path_type = L4C_MCF_PATH_TYPE_RUNTIME;
kal_wsprintf(filename, "%s\\%s\0", MCF_FS_CUSTOM_FOLDER_PATH, MCF_FS_DEFAULT_TLVOTA_FILE_NAME);
}
} else {
if (is_booting == KAL_TRUE) {
com_Mcf.boot_trace_flag |= MCF_BOOT_TRACE_F_READ_OTA_FILE_FAIL;
MCF_BOOT_TRACE(MCF_BOOT_TR_READ_TLVOTA_FILE_COMPARE_FAIL);
}
MD_TRC_MCF_TR_READ_TLVOTA_FILE_COMPARE_FAIL();
ret = MCF_OTA_R_READ_OTA_FILE_FAIL;
return ret;
}
strncpy(apply_filename, MCF_FS_DEFAULT_TLVOTA_FILE_NAME, MCF_FILE_MAX_NAME_LEN - 1);
fs_api_ret[0] = MCF_FS_CMPT_Read(filename, &fs_cmpt);
if (fs_api_ret[0] < FS_NO_ERROR) {
if (is_booting == KAL_TRUE) {
com_Mcf.boot_trace_flag |= MCF_BOOT_TRACE_F_READ_TLVOTA_FILE_FAIL;
MCF_BOOT_TRACE(MCF_BOOT_TR_READ_TLVOTA_FILE_FAIL, *apply_path_type, sim_id, fs_api_ret[0]);
MCF_BOOT_TRACE(MCF_BOOT_TR_STRING, apply_filename);
}
MD_TRC_MCF_TR_READ_TLVOTA_FILE_FAIL(*apply_path_type, sim_id, fs_api_ret[0]);
dhl_print_string(TRACE_INFO, DHL_USER_FLAG_NONE, MOD_MCF, apply_filename);
ret = MCF_OTA_R_READ_OTA_FILE_FAIL;
return ret;
}
} else {
ret = MCF_OTA_R_READ_OTA_FILE_FAIL;
return ret;
}
}
if (file_size > MCF_MAX_TLVOTA_FILE_SIZE) {
if (is_booting == KAL_TRUE) {
com_Mcf.boot_trace_flag |= MCF_BOOT_TRACE_F_TLVOTA_FILE_OVERSIZE;
MCF_BOOT_TRACE(MCF_BOOT_TR_READ_TLVOTA_FILE_OVERSIZE, file_size, MCF_MAX_TLVOTA_FILE_SIZE);
}
MD_TRC_MCF_TR_READ_TLVOTA_FILE_OVERSIZE(file_size, MCF_MAX_TLVOTA_FILE_SIZE);
ret = MCF_OTA_R_READ_OTA_FILE_FAIL;
return ret;
}
/* Read file */
fs_cmpt.opid_map = NVRAM_FS_CMPT_OPEN | NVRAM_FS_CMPT_READ | NVRAM_FS_CMPT_CLOSE;
fs_cmpt.Flag = FS_READ_ONLY;
fs_cmpt.Length = file_size;
fs_cmpt.Offset = 0;
fs_cmpt.Whence = FS_FILE_BEGIN;
fs_cmpt.DataPtr = tlvota_file->buff;
fs_cmpt.Read = &read_byte;
fs_cmpt.FileSize = &dummy_para;
fs_api_ret[*apply_path_type] = FS_GetFileDetail(filename, &fs_file_detail[*apply_path_type]);
MD_TRC_MCF_TR_READ_TLVOTA_FILE_MODIFIED_TIME(*apply_path_type, fs_api_ret[*apply_path_type],
(kal_uint32)((fs_file_detail[*apply_path_type].LastStatusChangeTime >> 32) & 0xFFFFFFFF), (kal_uint32)(fs_file_detail[*apply_path_type].LastStatusChangeTime & 0xFFFFFFFF));
if (fs_api_ret[*apply_path_type] == FS_NO_ERROR) {
last_mod_time = fs_file_detail[*apply_path_type].LastStatusChangeTime;
} else {
if (is_booting == KAL_TRUE) {
com_Mcf.boot_trace_flag |= MCF_BOOT_TRACE_F_READ_TLVOTA_FILE_FAIL;
MCF_BOOT_TRACE(MCF_BOOT_TR_READ_TLVOTA_FILE_FAIL, *apply_path_type, sim_id, fs_api_ret[0]);
MCF_BOOT_TRACE(MCF_BOOT_TR_STRING, apply_filename);
}
MD_TRC_MCF_TR_READ_TLVOTA_FILE_FAIL(*apply_path_type, sim_id, fs_api_ret[*apply_path_type]);
dhl_print_string(TRACE_INFO, DHL_USER_FLAG_NONE, MOD_MCF, apply_filename);
ret = MCF_OTA_R_READ_OTA_FILE_FAIL;
return ret;
}
MCF_W_LOCK_OBJECT(tlvota_file, mcf_enhmutex_g);
if (tlvota_file) {
fs_api_ret[0] = MCF_FS_CMPT_Read(filename, &fs_cmpt);
if (fs_api_ret[0] < FS_NO_ERROR) {
MCF_W_UNLOCK_OBJECT(tlvota_file, mcf_enhmutex_g);
if (is_booting == KAL_TRUE) {
com_Mcf.boot_trace_flag |= MCF_BOOT_TRACE_F_READ_TLVOTA_FILE_FAIL;
MCF_BOOT_TRACE(MCF_BOOT_TR_READ_TLVOTA_FILE_FAIL, *apply_path_type, sim_id, fs_api_ret[0]);
MCF_BOOT_TRACE(MCF_BOOT_TR_STRING, apply_filename);
}
MD_TRC_MCF_TR_READ_TLVOTA_FILE_FAIL(*apply_path_type, sim_id, fs_api_ret[0]);
dhl_print_string(TRACE_INFO, DHL_USER_FLAG_NONE, MOD_MCF, apply_filename);
ret = MCF_OTA_R_READ_OTA_FILE_FAIL;
return ret;
}
pFile = (mcf_tool_file_info_t *)(tlvota_file->buff);
#ifdef __MCF_FIND_TAG_SUPPORT__
if (pFile->file_version == 2 || pFile->file_version == 3) {
#else
if (pFile->file_version == 3) {
#endif
kal_uint32 operation_mask = 0;
/* Check custom operation mask */
operation_mask = mcf_get_custom_operation_mask();
if ((pFile->operation_mask & operation_mask) != operation_mask) {
if (is_booting == KAL_TRUE) {
com_Mcf.boot_trace_flag |= MCF_BOOT_TRACE_F_OPERATION_MASK_FAIL;
MCF_BOOT_TRACE(MCF_BOOT_TR_READ_TLVOTA_FILE_OPERATION_MASK_FAIL, apply_filename, pFile->operation_mask, operation_mask);
}
MD_TRC_MCF_TR_READ_TLVOTA_FILE_OPERATION_MASK_FAIL(apply_filename, pFile->operation_mask, operation_mask);
ret = MCF_OTA_R_INVALID_FILE;
kal_mem_set(tlvota_file->buff, 0, MCF_MAX_TLVOTA_FILE_SIZE);
kal_mem_set(tlvota_file->relative_path_name, 0, MCF_FILE_MAX_NAME_LEN);
tlvota_file->path_type = 0;
tlvota_file->last_mod_time = 0;
kal_mem_set(&(tlvota_file->last_file), 0, sizeof(mcf_file_info_t));
MCF_W_UNLOCK_OBJECT(tlvota_file, mcf_enhmutex_g);
return ret;
}
/* First check digest first
* If file is encrypted and has checksum.
* Decrypt file before checking checksum.
*/
// RSA verify digest
if ((pFile->operation_mask & MCF_FILE_OP_SHA256_RSA2048) != 0) {
if (mcf_verify_digest(MCF_FILE_OP_SHA256_RSA2048, (mcf_tool_file_info_t *)(tlvota_file->buff), (mcf_digest *)(tlvota_file->buff + pFile->file_size)) != KAL_TRUE) {
kal_mem_set(tlvota_file->buff, 0, MCF_MAX_TLVOTA_FILE_SIZE);
kal_mem_set(tlvota_file->relative_path_name, 0, MCF_FILE_MAX_NAME_LEN);
tlvota_file->path_type = 0;
tlvota_file->last_mod_time = 0;
kal_mem_set(&(tlvota_file->last_file), 0, sizeof(mcf_file_info_t));
MCF_W_UNLOCK_OBJECT(tlvota_file, mcf_enhmutex_g);
if (is_booting == KAL_TRUE) {
com_Mcf.boot_trace_flag |= MCF_BOOT_TRACE_F_DIGEST_FAIL;
MCF_BOOT_TRACE(MCF_BOOT_TR_READ_TLVOTA_FILE_DIGEST_FAIL, apply_filename);
}
MD_TRC_MCF_TR_READ_TLVOTA_FILE_DIGEST_FAIL(apply_filename);
ret = MCF_OTA_R_DIGEST_FAIL;
return ret;
}
}
else if ((pFile->operation_mask & MCF_FILE_OP_SHA384_RSA3072) != 0) {
if (mcf_verify_digest(MCF_FILE_OP_SHA384_RSA3072, (mcf_tool_file_info_t *)(tlvota_file->buff), (mcf_digest *)(tlvota_file->buff + pFile->file_size)) != KAL_TRUE) {
kal_mem_set(tlvota_file->buff, 0, MCF_MAX_TLVOTA_FILE_SIZE);
kal_mem_set(tlvota_file->relative_path_name, 0, MCF_FILE_MAX_NAME_LEN);
tlvota_file->path_type = 0;
tlvota_file->last_mod_time = 0;
kal_mem_set(&(tlvota_file->last_file), 0, sizeof(mcf_file_info_t));
MCF_W_UNLOCK_OBJECT(tlvota_file, mcf_enhmutex_g);
if (is_booting == KAL_TRUE) {
com_Mcf.boot_trace_flag |= MCF_BOOT_TRACE_F_DIGEST_FAIL;
MCF_BOOT_TRACE(MCF_BOOT_TR_READ_TLVOTA_FILE_DIGEST_FAIL, apply_filename);
}
MD_TRC_MCF_TR_READ_TLVOTA_FILE_DIGEST_FAIL(apply_filename);
ret = MCF_OTA_R_DIGEST_FAIL;
return ret;
}
}
if ( (pFile->operation_mask & MCF_FILE_OP_AES_128) != 0) {
mcf_get_custom_aes_password(password);
if (mcf_decrypt_128bit(password, (kal_char *)(tlvota_file->buff + pFile->total_len), (pFile->file_size - pFile->total_len) ) != KAL_TRUE) {
kal_mem_set(tlvota_file->buff, 0, MCF_MAX_TLVOTA_FILE_SIZE);
kal_mem_set(tlvota_file->relative_path_name, 0, MCF_FILE_MAX_NAME_LEN);
tlvota_file->path_type = 0;
tlvota_file->last_mod_time = 0;
kal_mem_set(&(tlvota_file->last_file), 0, sizeof(mcf_file_info_t));
MCF_W_UNLOCK_OBJECT(tlvota_file, mcf_enhmutex_g);
if (is_booting == KAL_TRUE) {
com_Mcf.boot_trace_flag |= MCF_BOOT_TRACE_F_DECRYPTION_FAIL;
MCF_BOOT_TRACE(MCF_BOOT_TR_READ_TLVOTA_FILE_DECRYPTION_FAIL, apply_filename);
}
MD_TRC_MCF_TR_READ_TLVOTA_FILE_DECRYPTION_FAIL(apply_filename);
ret = MCF_OTA_R_DECRYPTION_FAIL;
return ret;
}
}
else if ((pFile->operation_mask & MCF_FILE_OP_AES_256) != 0) { // for AES_256
mcf_get_custom_aes_password(password);
if (mcf_decrypt_256bit(password, (kal_char *)(tlvota_file->buff + pFile->total_len), (pFile->file_size - pFile->total_len)) != KAL_TRUE) {
kal_mem_set(tlvota_file->buff, 0, MCF_MAX_TLVOTA_FILE_SIZE);
kal_mem_set(tlvota_file->relative_path_name, 0, MCF_FILE_MAX_NAME_LEN);
tlvota_file->path_type = 0;
tlvota_file->last_mod_time = 0;
kal_mem_set(&(tlvota_file->last_file), 0, sizeof(mcf_file_info_t));
MCF_W_UNLOCK_OBJECT(tlvota_file, mcf_enhmutex_g);
if (is_booting == KAL_TRUE) {
com_Mcf.boot_trace_flag |= MCF_BOOT_TRACE_F_DECRYPTION_FAIL;
MCF_BOOT_TRACE(MCF_BOOT_TR_READ_TLVOTA_FILE_DECRYPTION_FAIL, apply_filename);
}
MD_TRC_MCF_TR_READ_TLVOTA_FILE_DECRYPTION_FAIL(apply_filename);
ret = MCF_OTA_R_DECRYPTION_FAIL;
return ret;
}
}
if ( (pFile->operation_mask & MCF_FILE_OP_CHECKSUM) != 0) {
if (mcf_check_check_sum((kal_uint32 *)(tlvota_file->buff), pFile->file_size) != 0) {
kal_mem_set(tlvota_file->buff, 0, MCF_MAX_TLVOTA_FILE_SIZE);
kal_mem_set(tlvota_file->relative_path_name, 0, MCF_FILE_MAX_NAME_LEN);
tlvota_file->path_type = 0;
tlvota_file->last_mod_time = 0;
kal_mem_set(&(tlvota_file->last_file), 0, sizeof(mcf_file_info_t));
MCF_W_UNLOCK_OBJECT(tlvota_file, mcf_enhmutex_g);
if (is_booting == KAL_TRUE) {
com_Mcf.boot_trace_flag |= MCF_BOOT_TRACE_F_CHECKSUM_ERROR;
MCF_BOOT_TRACE(MCF_BOOT_TR_READ_TLVOTA_FILE_CHECKSUM_ERROR, apply_filename);
}
MD_TRC_MCF_TR_READ_TLVOTA_FILE_CHECKSUM_ERROR(apply_filename);
ret = MCF_OTA_R_CHECKSUM_ERROR;
return ret;
}
}
} else {
if (is_booting == KAL_TRUE) {
com_Mcf.boot_trace_flag |= MCF_BOOT_TRACE_F_INVALID_FILE;
MCF_BOOT_TRACE(MCF_BOOT_TR_READ_TLVOTA_FILE_INVALID_FILE_VERSION, pFile->file_version);
}
MD_TRC_MCF_TR_READ_TLVOTA_FILE_INVALID_FILE_VERSION(apply_filename);
kal_mem_set(tlvota_file->buff, 0, MCF_MAX_TLVOTA_FILE_SIZE);
kal_mem_set(tlvota_file->relative_path_name, 0, MCF_FILE_MAX_NAME_LEN);
tlvota_file->path_type = 0;
tlvota_file->last_mod_time = 0;
kal_mem_set(&(tlvota_file->last_file), 0, sizeof(mcf_file_info_t));
MCF_W_UNLOCK_OBJECT(tlvota_file, mcf_enhmutex_g);
ret = MCF_OTA_R_INVALID_FILE;
return ret;
}
tlvota_file->path_type = *apply_path_type;
tlvota_file->last_mod_time = last_mod_time;
tlvota_file->last_file.last_mod_time = last_mod_time;
#if defined(__MCF_UT_FRAMEWORK_SUPPORT__)
if (strcmp(tlvota_file->relative_path_name, "") == 0){
strncpy(tlvota_file->relative_path_name, apply_filename, MCF_FILE_MAX_NAME_LEN - 1);
}else{
strncpy(apply_filename, tlvota_file->relative_path_name, MCF_FILE_MAX_NAME_LEN - 1);
}
#else
strncpy(tlvota_file->relative_path_name, apply_filename, MCF_FILE_MAX_NAME_LEN - 1);
#endif
MCF_W_UNLOCK_OBJECT(tlvota_file, mcf_enhmutex_g);
} else {
if (is_booting == KAL_TRUE) {
com_Mcf.boot_trace_flag |= MCF_BOOT_TRACE_F_TAKE_WRITE_LOCK_FAIL;
MCF_BOOT_TRACE(MCF_BOOT_TR_READ_TLVOTA_FILE_TAKE_WRITE_LOCK_FAIL, apply_filename, *apply_path_type, sim_id);
}
MD_TRC_MCF_TR_READ_TLVOTA_FILE_TAKE_WRITE_LOCK_FAIL(apply_filename, *apply_path_type, sim_id);
ret = MCF_OTA_R_READ_OTA_FILE_FAIL;
}
return ret;
}
mcf_ota_result_e mcf_read_general_tlvota_file(
kal_bool is_booting,
kal_char *req_fs_root_path,
kal_char *req_file_path_name,
l4c_mcf_path_type_enum *apply_path_type,
kal_char *apply_filename,
mcf_t *pMcf)
{
NVRAM_FS_PARAM_CMPT_T fs_cmpt;
FS_FileDetail fs_file_detail[L4C_MCF_PATH_TYPE_MAX] = {0};
kal_uint32 read_byte = 0;
kal_uint32 file_size = 0;
mcf_ota_result_e ret = MCF_OTA_R_SUCCESS;
mcf_tlvota_file_t *tlvota_file = &(pMcf->general_tlvota_file);
kal_wchar filename[MCF_FILE_MAX_MD_PATH_LEN + MCF_FILE_MAX_NAME_LEN];
mcf_tool_file_info_t *pFile;
kal_char password[MCF_MAX_PASSWORD_LEN] = {0};
kal_bool is_default_path;
kal_uint32 dummy_para;
kal_int32 fs_api_ret[L4C_MCF_PATH_TYPE_MAX];
kal_uint64 last_mod_time = 0;
mcf_tool_gid_tlvota_file_item_t *pItem;
kal_uint16 item_cnt = 0;
com_Mcf.is_iccid = KAL_FALSE;
fs_cmpt.opid_map = NVRAM_FS_CMPT_OPEN | NVRAM_FS_CMPT_GETFILESIZE | NVRAM_FS_CMPT_CLOSE;
fs_cmpt.Flag = FS_READ_ONLY;
fs_cmpt.Length = 0;
fs_cmpt.Offset = 0;
fs_cmpt.Whence = FS_FILE_BEGIN;
fs_cmpt.DataPtr = &dummy_para;
fs_cmpt.Read = &dummy_para;
fs_cmpt.FileSize = &file_size;
if ( (strcmp(req_fs_root_path, "") != 0) && (strcmp(req_file_path_name, "") != 0) ) {
if (strcmp(req_fs_root_path, MCF_FS_DEFAULT_FOLDER_PATH) == 0) {
*apply_path_type = L4C_MCF_PATH_TYPE_OTA;
} else if (strcmp(req_fs_root_path, MCF_FS_CUSTOM_FOLDER_PATH) == 0) {
*apply_path_type = L4C_MCF_PATH_TYPE_RUNTIME;
} else{
MD_TRC_MCF_TR_READ_GENERAL_TLVOTA_FILE_INVALID_PATH(req_fs_root_path);
ret = MCF_OTA_R_INVALID_PARAMETER;
return ret;
}
kal_wsprintf(filename, "%s\\%s\0", req_fs_root_path, req_file_path_name);
strncpy(apply_filename, req_file_path_name, MCF_FILE_MAX_NAME_LEN - 1);
is_default_path = KAL_FALSE;
} else {
/* Compare modified time of general OP-OTA file to select which file to be applied */
kal_wsprintf(filename, "%s\\%s\0", MCF_FS_DEFAULT_FOLDER_PATH, MCF_FS_GENERAL_TLVOTA_FILE_NAME);
fs_api_ret[L4C_MCF_PATH_TYPE_OTA] = FS_GetFileDetail(filename, &fs_file_detail[L4C_MCF_PATH_TYPE_OTA]);
MD_TRC_MCF_TR_READ_GENERAL_TLVOTA_FILE_MODIFIED_TIME(L4C_MCF_PATH_TYPE_OTA, fs_api_ret[L4C_MCF_PATH_TYPE_OTA],
(kal_uint32)((fs_file_detail[L4C_MCF_PATH_TYPE_OTA].LastStatusChangeTime >> 32) & 0xFFFFFFFF), (kal_uint32)(fs_file_detail[L4C_MCF_PATH_TYPE_OTA].LastStatusChangeTime & 0xFFFFFFFF));
if (fs_api_ret[L4C_MCF_PATH_TYPE_OTA] != FS_NO_ERROR) {
kal_mem_set(&fs_file_detail[L4C_MCF_PATH_TYPE_OTA], 0, sizeof(FS_FileDetail));
}
kal_wsprintf(filename, "%s\\%s\0", MCF_FS_CUSTOM_FOLDER_PATH, MCF_FS_GENERAL_TLVOTA_FILE_NAME);
fs_api_ret[L4C_MCF_PATH_TYPE_RUNTIME] = FS_GetFileDetail(filename, &fs_file_detail[L4C_MCF_PATH_TYPE_RUNTIME]);
MD_TRC_MCF_TR_READ_GENERAL_TLVOTA_FILE_MODIFIED_TIME(L4C_MCF_PATH_TYPE_RUNTIME, fs_api_ret[L4C_MCF_PATH_TYPE_RUNTIME],
(kal_uint32)((fs_file_detail[L4C_MCF_PATH_TYPE_RUNTIME].LastStatusChangeTime >> 32) & 0xFFFFFFFF), (kal_uint32)(fs_file_detail[L4C_MCF_PATH_TYPE_RUNTIME].LastStatusChangeTime & 0xFFFFFFFF));
if (fs_api_ret[L4C_MCF_PATH_TYPE_RUNTIME] != FS_NO_ERROR) {
kal_mem_set(&fs_file_detail[L4C_MCF_PATH_TYPE_RUNTIME], 0, sizeof(FS_FileDetail));
}
if ( (fs_api_ret[L4C_MCF_PATH_TYPE_OTA] == FS_NO_ERROR) || (fs_api_ret[L4C_MCF_PATH_TYPE_RUNTIME] == FS_NO_ERROR) ) {
if (fs_file_detail[L4C_MCF_PATH_TYPE_OTA].LastStatusChangeTime > fs_file_detail[L4C_MCF_PATH_TYPE_RUNTIME].LastStatusChangeTime) {
*apply_path_type = L4C_MCF_PATH_TYPE_OTA;
kal_wsprintf(filename, "%s\\%s\0", MCF_FS_DEFAULT_FOLDER_PATH, MCF_FS_GENERAL_TLVOTA_FILE_NAME);
} else {
*apply_path_type = L4C_MCF_PATH_TYPE_RUNTIME;
kal_wsprintf(filename, "%s\\%s\0", MCF_FS_CUSTOM_FOLDER_PATH, MCF_FS_GENERAL_TLVOTA_FILE_NAME);
}
} else {
if (is_booting == KAL_TRUE) {
com_Mcf.boot_trace_flag |= MCF_BOOT_TRACE_F_READ_OTA_FILE_FAIL;
MCF_BOOT_TRACE(MCF_BOOT_TR_READ_GENERAL_TLVOTA_FILE_COMPARE_FAIL);
}
MD_TRC_MCF_TR_READ_GENERAL_TLVOTA_FILE_COMPARE_FAIL();
ret = MCF_OTA_R_READ_OTA_FILE_FAIL;
return ret;
}
strncpy(apply_filename, MCF_FS_GENERAL_TLVOTA_FILE_NAME, MCF_FILE_MAX_NAME_LEN - 1);
is_default_path = KAL_TRUE;
}
fs_api_ret[0] = MCF_FS_CMPT_Read(filename, &fs_cmpt);
if (fs_api_ret[0] < FS_NO_ERROR) {
if (is_booting == KAL_TRUE) {
MCF_BOOT_TRACE(MCF_BOOT_TR_READ_GENERAL_TLVOTA_FILE_FAIL, *apply_path_type, fs_api_ret[0]);
MCF_BOOT_TRACE(MCF_BOOT_TR_STRING, apply_filename);
}
MD_TRC_MCF_TR_READ_GENERAL_TLVOTA_FILE_FAIL(*apply_path_type, fs_api_ret[0]);
dhl_print_string(TRACE_INFO, DHL_USER_FLAG_NONE, MOD_MCF, apply_filename);
/* If cannot read given TLV-OTA file, read default TLV-OTA file */
if (is_default_path == KAL_FALSE) {
/* Compare modified time of general OP-OTA file to select which file to be applied */
kal_wsprintf(filename, "%s\\%s\0", MCF_FS_DEFAULT_FOLDER_PATH, MCF_FS_GENERAL_TLVOTA_FILE_NAME);
fs_api_ret[L4C_MCF_PATH_TYPE_OTA] = FS_GetFileDetail(filename, &fs_file_detail[L4C_MCF_PATH_TYPE_OTA]);
MD_TRC_MCF_TR_READ_GENERAL_TLVOTA_FILE_MODIFIED_TIME(L4C_MCF_PATH_TYPE_OTA, fs_api_ret[L4C_MCF_PATH_TYPE_OTA],
(kal_uint32)((fs_file_detail[L4C_MCF_PATH_TYPE_OTA].LastStatusChangeTime >> 32) & 0xFFFFFFFF), (kal_uint32)(fs_file_detail[L4C_MCF_PATH_TYPE_OTA].LastStatusChangeTime & 0xFFFFFFFF));
if (fs_api_ret[L4C_MCF_PATH_TYPE_OTA] != FS_NO_ERROR) {
kal_mem_set(&fs_file_detail[L4C_MCF_PATH_TYPE_OTA], 0, sizeof(FS_FileDetail));
}
kal_wsprintf(filename, "%s\\%s\0", MCF_FS_CUSTOM_FOLDER_PATH, MCF_FS_GENERAL_TLVOTA_FILE_NAME);
fs_api_ret[L4C_MCF_PATH_TYPE_RUNTIME] = FS_GetFileDetail(filename, &fs_file_detail[L4C_MCF_PATH_TYPE_RUNTIME]);
MD_TRC_MCF_TR_READ_GENERAL_TLVOTA_FILE_MODIFIED_TIME(L4C_MCF_PATH_TYPE_RUNTIME, fs_api_ret[L4C_MCF_PATH_TYPE_RUNTIME],
(kal_uint32)((fs_file_detail[L4C_MCF_PATH_TYPE_RUNTIME].LastStatusChangeTime >> 32) & 0xFFFFFFFF), (kal_uint32)(fs_file_detail[L4C_MCF_PATH_TYPE_RUNTIME].LastStatusChangeTime & 0xFFFFFFFF));
if (fs_api_ret[L4C_MCF_PATH_TYPE_RUNTIME] != FS_NO_ERROR) {
kal_mem_set(&fs_file_detail[L4C_MCF_PATH_TYPE_RUNTIME], 0, sizeof(FS_FileDetail));
}
if ( (fs_api_ret[L4C_MCF_PATH_TYPE_OTA] == FS_NO_ERROR) || (fs_api_ret[L4C_MCF_PATH_TYPE_RUNTIME] == FS_NO_ERROR) ) {
if (fs_file_detail[L4C_MCF_PATH_TYPE_OTA].LastStatusChangeTime > fs_file_detail[L4C_MCF_PATH_TYPE_RUNTIME].LastStatusChangeTime) {
*apply_path_type = L4C_MCF_PATH_TYPE_OTA;
kal_wsprintf(filename, "%s\\%s\0", MCF_FS_DEFAULT_FOLDER_PATH, MCF_FS_GENERAL_TLVOTA_FILE_NAME);
} else {
*apply_path_type = L4C_MCF_PATH_TYPE_RUNTIME;
kal_wsprintf(filename, "%s\\%s\0", MCF_FS_CUSTOM_FOLDER_PATH, MCF_FS_GENERAL_TLVOTA_FILE_NAME);
}
} else {
if (is_booting == KAL_TRUE) {
com_Mcf.boot_trace_flag |= MCF_BOOT_TRACE_F_READ_OTA_FILE_FAIL;
MCF_BOOT_TRACE(MCF_BOOT_TR_READ_GENERAL_TLVOTA_FILE_COMPARE_FAIL);
}
MD_TRC_MCF_TR_READ_GENERAL_TLVOTA_FILE_COMPARE_FAIL();
ret = MCF_OTA_R_READ_OTA_FILE_FAIL;
return ret;
}
strncpy(apply_filename, MCF_FS_GENERAL_TLVOTA_FILE_NAME, MCF_FILE_MAX_NAME_LEN - 1);
fs_api_ret[0] = MCF_FS_CMPT_Read(filename, &fs_cmpt);
if (fs_api_ret[0] < FS_NO_ERROR) {
if (is_booting == KAL_TRUE) {
com_Mcf.boot_trace_flag |= MCF_BOOT_TRACE_F_READ_TLVOTA_FILE_FAIL;
MCF_BOOT_TRACE(MCF_BOOT_TR_READ_GENERAL_TLVOTA_FILE_FAIL, *apply_path_type, fs_api_ret[0]);
MCF_BOOT_TRACE(MCF_BOOT_TR_STRING, apply_filename);
}
MD_TRC_MCF_TR_READ_GENERAL_TLVOTA_FILE_FAIL(*apply_path_type, fs_api_ret[0]);
dhl_print_string(TRACE_INFO, DHL_USER_FLAG_NONE, MOD_MCF, apply_filename);
ret = MCF_OTA_R_READ_OTA_FILE_FAIL;
return ret;
}
} else {
ret = MCF_OTA_R_READ_OTA_FILE_FAIL;
return ret;
}
}
if (file_size > MCF_MAX_TLVOTA_FILE_SIZE) {
if (is_booting == KAL_TRUE) {
com_Mcf.boot_trace_flag |= MCF_BOOT_TRACE_F_TLVOTA_FILE_OVERSIZE;
MCF_BOOT_TRACE(MCF_BOOT_TR_READ_GENERAL_TLVOTA_FILE_OVERSIZE, file_size, MCF_MAX_TLVOTA_FILE_SIZE);
}
MD_TRC_MCF_TR_READ_GENERAL_TLVOTA_FILE_OVERSIZE(file_size, MCF_MAX_TLVOTA_FILE_SIZE);
ret = MCF_OTA_R_READ_OTA_FILE_FAIL;
return ret;
}
/* Read file */
fs_cmpt.opid_map = NVRAM_FS_CMPT_OPEN | NVRAM_FS_CMPT_READ | NVRAM_FS_CMPT_CLOSE;
fs_cmpt.Flag = FS_READ_ONLY;
fs_cmpt.Length = file_size;
fs_cmpt.Offset = 0;
fs_cmpt.Whence = FS_FILE_BEGIN;
fs_cmpt.DataPtr = tlvota_file->buff;
fs_cmpt.Read = &read_byte;
fs_cmpt.FileSize = &dummy_para;
fs_api_ret[*apply_path_type] = FS_GetFileDetail(filename, &fs_file_detail[*apply_path_type]);
MD_TRC_MCF_TR_READ_GENERAL_TLVOTA_FILE_MODIFIED_TIME(*apply_path_type, fs_api_ret[*apply_path_type],
(kal_uint32)((fs_file_detail[*apply_path_type].LastStatusChangeTime >> 32) & 0xFFFFFFFF), (kal_uint32)(fs_file_detail[*apply_path_type].LastStatusChangeTime & 0xFFFFFFFF));
if (fs_api_ret[*apply_path_type] == FS_NO_ERROR) {
last_mod_time = fs_file_detail[*apply_path_type].LastStatusChangeTime;
} else {
if (is_booting == KAL_TRUE) {
com_Mcf.boot_trace_flag |= MCF_BOOT_TRACE_F_READ_TLVOTA_FILE_FAIL;
MCF_BOOT_TRACE(MCF_BOOT_TR_READ_GENERAL_TLVOTA_FILE_FAIL, *apply_path_type, fs_api_ret[0]);
MCF_BOOT_TRACE(MCF_BOOT_TR_STRING, apply_filename);
}
MD_TRC_MCF_TR_READ_GENERAL_TLVOTA_FILE_FAIL(*apply_path_type, fs_api_ret[*apply_path_type]);
dhl_print_string(TRACE_INFO, DHL_USER_FLAG_NONE, MOD_MCF, apply_filename);
ret = MCF_OTA_R_READ_OTA_FILE_FAIL;
return ret;
}
MCF_W_LOCK_OBJECT(tlvota_file, mcf_enhmutex_g);
if (tlvota_file) {
fs_api_ret[0] = MCF_FS_CMPT_Read(filename, &fs_cmpt);
if (fs_api_ret[0] < FS_NO_ERROR) {
MCF_W_UNLOCK_OBJECT(tlvota_file, mcf_enhmutex_g);
if (is_booting == KAL_TRUE) {
com_Mcf.boot_trace_flag |= MCF_BOOT_TRACE_F_READ_TLVOTA_FILE_FAIL;
MCF_BOOT_TRACE(MCF_BOOT_TR_READ_GENERAL_TLVOTA_FILE_FAIL, *apply_path_type, fs_api_ret[0]);
MCF_BOOT_TRACE(MCF_BOOT_TR_STRING, apply_filename);
}
MD_TRC_MCF_TR_READ_GENERAL_TLVOTA_FILE_FAIL(*apply_path_type, fs_api_ret[0]);
dhl_print_string(TRACE_INFO, DHL_USER_FLAG_NONE, MOD_MCF, apply_filename);
ret = MCF_OTA_R_READ_OTA_FILE_FAIL;
return ret;
}
com_Mcf.is_iccid = KAL_FALSE;
pFile = (mcf_tool_file_info_t *)(tlvota_file->buff);
#ifdef __MCF_FIND_TAG_SUPPORT__
if (pFile->file_version == 2 || pFile->file_version == 3) {
#else
if (pFile->file_version == 3) {
#endif
kal_uint32 operation_mask = 0;
/* Check custom operation mask */
operation_mask = mcf_get_custom_operation_mask();
if ((pFile->operation_mask & operation_mask) != operation_mask) {
if (is_booting == KAL_TRUE) {
com_Mcf.boot_trace_flag |= MCF_BOOT_TRACE_F_OPERATION_MASK_FAIL;
MCF_BOOT_TRACE(MCF_BOOT_TR_READ_GENERAL_TLVOTA_FILE_OPERATION_MASK_FAIL, apply_filename, pFile->operation_mask, operation_mask);
}
MD_TRC_MCF_TR_READ_GENERAL_TLVOTA_FILE_OPERATION_MASK_FAIL(apply_filename, pFile->operation_mask, operation_mask);
ret = MCF_OTA_R_INVALID_FILE;
kal_mem_set(tlvota_file->buff, 0, MCF_MAX_TLVOTA_FILE_SIZE);
kal_mem_set(tlvota_file->relative_path_name, 0, MCF_FILE_MAX_NAME_LEN);
tlvota_file->path_type = 0;
tlvota_file->last_mod_time = 0;
kal_mem_set(&(tlvota_file->last_file), 0, sizeof(mcf_file_info_t));
MCF_W_UNLOCK_OBJECT(tlvota_file, mcf_enhmutex_g);
return ret;
}
/* First check digest first
* If file is encrypted and has checksum.
* Decrypt file before checking checksum.
*/
// RSA verify digest
if ((pFile->operation_mask & MCF_FILE_OP_SHA256_RSA2048) != 0) {
if (mcf_verify_digest(MCF_FILE_OP_SHA256_RSA2048, (mcf_tool_file_info_t *)(tlvota_file->buff), (mcf_digest *)(tlvota_file->buff + pFile->file_size)) != KAL_TRUE) {
kal_mem_set(tlvota_file->buff, 0, MCF_MAX_TLVOTA_FILE_SIZE );
kal_mem_set(tlvota_file->relative_path_name, 0, MCF_FILE_MAX_NAME_LEN);
tlvota_file->path_type = 0;
tlvota_file->last_mod_time = 0;
kal_mem_set(&(tlvota_file->last_file), 0, sizeof(mcf_file_info_t));
MCF_W_UNLOCK_OBJECT(tlvota_file, mcf_enhmutex_g);
if (is_booting == KAL_TRUE) {
com_Mcf.boot_trace_flag |= MCF_BOOT_TRACE_F_DIGEST_FAIL;
MCF_BOOT_TRACE(MCF_BOOT_TR_READ_GENERAL_TLVOTA_FILE_DIGEST_FAIL, apply_filename);
}
MD_TRC_MCF_TR_READ_GENERAL_TLVOTA_FILE_DIGEST_FAIL(apply_filename);
ret = MCF_OTA_R_DIGEST_FAIL;
return ret;
}
}
else if ((pFile->operation_mask & MCF_FILE_OP_SHA384_RSA3072) != 0) {
if (mcf_verify_digest(MCF_FILE_OP_SHA384_RSA3072, (mcf_tool_file_info_t *)(tlvota_file->buff), (mcf_digest *)(tlvota_file->buff + pFile->file_size)) != KAL_TRUE) {
kal_mem_set(tlvota_file->buff, 0, MCF_MAX_TLVOTA_FILE_SIZE );
kal_mem_set(tlvota_file->relative_path_name, 0, MCF_FILE_MAX_NAME_LEN);
tlvota_file->path_type = 0;
tlvota_file->last_mod_time = 0;
kal_mem_set(&(tlvota_file->last_file), 0, sizeof(mcf_file_info_t));
MCF_W_UNLOCK_OBJECT(tlvota_file, mcf_enhmutex_g);
if (is_booting == KAL_TRUE) {
com_Mcf.boot_trace_flag |= MCF_BOOT_TRACE_F_DIGEST_FAIL;
MCF_BOOT_TRACE(MCF_BOOT_TR_READ_GENERAL_TLVOTA_FILE_DIGEST_FAIL, apply_filename);
}
MD_TRC_MCF_TR_READ_GENERAL_TLVOTA_FILE_DIGEST_FAIL(apply_filename);
ret = MCF_OTA_R_DIGEST_FAIL;
return ret;
}
}
if ( (pFile->operation_mask & MCF_FILE_OP_AES_128) != 0) {
mcf_get_custom_aes_password(password);
if (mcf_decrypt_128bit(password, (kal_char *)(tlvota_file->buff + pFile->total_len), (pFile->file_size - pFile->total_len) ) != KAL_TRUE) {
kal_mem_set(tlvota_file->buff, 0, MCF_MAX_TLVOTA_FILE_SIZE );
kal_mem_set(tlvota_file->relative_path_name, 0, MCF_FILE_MAX_NAME_LEN);
tlvota_file->path_type = 0;
tlvota_file->last_mod_time = 0;
kal_mem_set(&(tlvota_file->last_file), 0, sizeof(mcf_file_info_t));
MCF_W_UNLOCK_OBJECT(tlvota_file, mcf_enhmutex_g);
if (is_booting == KAL_TRUE) {
com_Mcf.boot_trace_flag |= MCF_BOOT_TRACE_F_DECRYPTION_FAIL;
MCF_BOOT_TRACE(MCF_BOOT_TR_READ_GENERAL_TLVOTA_FILE_DECRYPTION_FAIL, apply_filename);
}
MD_TRC_MCF_TR_READ_GENERAL_TLVOTA_FILE_DECRYPTION_FAIL(apply_filename);
ret = MCF_OTA_R_DECRYPTION_FAIL;
return ret;
}
}
else if ((pFile->operation_mask & MCF_FILE_OP_AES_256) != 0) { // for AES_256
mcf_get_custom_aes_password(password);
if (mcf_decrypt_256bit(password, (kal_char *)(tlvota_file->buff + pFile->total_len), (pFile->file_size - pFile->total_len)) != KAL_TRUE) {
kal_mem_set(tlvota_file->buff, 0, MCF_MAX_TLVOTA_FILE_SIZE);
kal_mem_set(tlvota_file->relative_path_name, 0, MCF_FILE_MAX_NAME_LEN);
tlvota_file->path_type = 0;
tlvota_file->last_mod_time = 0;
kal_mem_set(&(tlvota_file->last_file), 0, sizeof(mcf_file_info_t));
MCF_W_UNLOCK_OBJECT(tlvota_file, mcf_enhmutex_g);
if (is_booting == KAL_TRUE) {
com_Mcf.boot_trace_flag |= MCF_BOOT_TRACE_F_DECRYPTION_FAIL;
MCF_BOOT_TRACE(MCF_BOOT_TR_READ_GENERAL_TLVOTA_FILE_DECRYPTION_FAIL, apply_filename);
}
MD_TRC_MCF_TR_READ_GENERAL_TLVOTA_FILE_DECRYPTION_FAIL(apply_filename);
ret = MCF_OTA_R_DECRYPTION_FAIL;
return ret;
}
}
if ( (pFile->operation_mask & MCF_FILE_OP_CHECKSUM) != 0) {
if (mcf_check_check_sum((kal_uint32 *)(tlvota_file->buff), pFile->file_size) != 0) {
kal_mem_set(tlvota_file->buff, 0, MCF_MAX_TLVOTA_FILE_SIZE);
kal_mem_set(tlvota_file->relative_path_name, 0, MCF_FILE_MAX_NAME_LEN);
tlvota_file->path_type = 0;
tlvota_file->last_mod_time = 0;
kal_mem_set(&(tlvota_file->last_file), 0, sizeof(mcf_file_info_t));
MCF_W_UNLOCK_OBJECT(tlvota_file, mcf_enhmutex_g);
if (is_booting == KAL_TRUE) {
com_Mcf.boot_trace_flag |= MCF_BOOT_TRACE_F_CHECKSUM_ERROR;
MCF_BOOT_TRACE(MCF_BOOT_TR_READ_GENERAL_TLVOTA_FILE_CHECKSUM_ERROR, apply_filename);
}
MD_TRC_MCF_TR_READ_GENERAL_TLVOTA_FILE_CHECKSUM_ERROR(apply_filename);
ret = MCF_OTA_R_CHECKSUM_ERROR;
return ret;
}
}
//Check whether general TLV-OTA have iccid tag
pItem = (mcf_tool_gid_tlvota_file_item_t *)(tlvota_file->buff + pFile->total_len);
while (item_cnt < pFile->item_num) {
if ((pItem->tag_type == MCF_TLVOTA_TAG_ICCID)) {
com_Mcf.is_iccid = KAL_TRUE;
MD_TRC_MCF_TR_READ_GENERAL_TLVOTA_FILE_TAG_TYPE(MCF_TLVOTA_TAG_ICCID);
break;
}
pItem = (mcf_tool_gid_tlvota_file_item_t *)((kal_uint8 *)pItem + pItem->total_len);
item_cnt++;
}
} else {
if (is_booting == KAL_TRUE) {
com_Mcf.boot_trace_flag |= MCF_BOOT_TRACE_F_INVALID_FILE;
MCF_BOOT_TRACE(MCF_BOOT_TR_READ_GENERAL_TLVOTA_FILE_INVALID_FILE_VERSION, pFile->file_version);
}
MD_TRC_MCF_TR_READ_GENERAL_TLVOTA_FILE_INVALID_FILE_VERSION(pFile->file_version);
kal_mem_set(tlvota_file->buff, 0, MCF_MAX_TLVOTA_FILE_SIZE);
kal_mem_set(tlvota_file->relative_path_name, 0, MCF_FILE_MAX_NAME_LEN);
tlvota_file->path_type = 0;
tlvota_file->last_mod_time = 0;
kal_mem_set(&(tlvota_file->last_file), 0, sizeof(mcf_file_info_t));
MCF_W_UNLOCK_OBJECT(tlvota_file, mcf_enhmutex_g);
ret = MCF_OTA_R_INVALID_FILE;
return ret;
}
tlvota_file->path_type = *apply_path_type;
#if defined(__MCF_UT_FRAMEWORK_SUPPORT__)
if (strcmp(tlvota_file->relative_path_name, "") == 0){
strncpy(tlvota_file->relative_path_name, apply_filename, MCF_FILE_MAX_NAME_LEN - 1);
}else{
strncpy(apply_filename, tlvota_file->relative_path_name, MCF_FILE_MAX_NAME_LEN - 1);
}
#else
strncpy(tlvota_file->relative_path_name, apply_filename, MCF_FILE_MAX_NAME_LEN - 1);
#endif
tlvota_file->last_mod_time = last_mod_time;
tlvota_file->last_file.last_mod_time = last_mod_time;
MCF_W_UNLOCK_OBJECT(tlvota_file, mcf_enhmutex_g);
} else {
if (is_booting == KAL_TRUE) {
com_Mcf.boot_trace_flag |= MCF_BOOT_TRACE_F_TAKE_WRITE_LOCK_FAIL;
MCF_BOOT_TRACE(MCF_BOOT_TR_READ_GENERAL_TLVOTA_FILE_TAKE_WRITE_LOCK_FAIL, apply_filename, *apply_path_type);
}
MD_TRC_MCF_TR_READ_GENERAL_TLVOTA_FILE_TAKE_WRITE_LOCK_FAIL(apply_filename, *apply_path_type);
ret = MCF_OTA_R_READ_OTA_FILE_FAIL;
}
return ret;
}
mcf_ota_result_e mcf_read_ini_file(
kal_char *req_fs_root_path,
kal_char *req_file_path_name,
l4c_mcf_path_type_enum *apply_path_type,
kal_char *apply_filename,
mcf_t *pMcf)
{
NVRAM_FS_PARAM_CMPT_T fs_cmpt;
kal_uint32 read_byte = 0;
kal_uint32 file_size = 0;
mcf_ota_result_e ret = MCF_OTA_R_SUCCESS;
mcf_ini_file_t *ini_file = &(pMcf->ini_file);
kal_wchar filename[MCF_FILE_MAX_MD_PATH_LEN + MCF_FILE_MAX_NAME_LEN];
kal_bool is_default_path;
kal_uint32 dummy_para;
kal_int32 fs_api_ret[L4C_MCF_PATH_TYPE_MAX];
fs_cmpt.opid_map = NVRAM_FS_CMPT_OPEN | NVRAM_FS_CMPT_GETFILESIZE | NVRAM_FS_CMPT_CLOSE;
fs_cmpt.Flag = FS_READ_ONLY;
fs_cmpt.Length = 0;
fs_cmpt.Offset = 0;
fs_cmpt.Whence = FS_FILE_BEGIN;
fs_cmpt.DataPtr = &dummy_para;
fs_cmpt.Read = &dummy_para;
fs_cmpt.FileSize = &file_size;
if ( (strcmp(req_fs_root_path, "") != 0) && (strcmp(req_file_path_name, "") != 0) ) {
if (strcmp(req_fs_root_path, MCF_FS_DEFAULT_FOLDER_PATH) == 0) {
*apply_path_type = L4C_MCF_PATH_TYPE_OTA;
} else if (strcmp(req_fs_root_path, MCF_FS_CUSTOM_FOLDER_PATH) == 0) {
*apply_path_type = L4C_MCF_PATH_TYPE_RUNTIME;
}
kal_wsprintf(filename, "%s\\%s\0", req_fs_root_path, req_file_path_name);
strncpy(apply_filename, req_file_path_name, MCF_FILE_MAX_NAME_LEN - 1);
is_default_path = KAL_FALSE;
} else {
if (*apply_path_type == L4C_MCF_PATH_TYPE_OTA) {
kal_wsprintf(filename, "%s\\%s\0", MCF_FS_DEFAULT_FOLDER_PATH, apply_filename);
} else if (*apply_path_type == L4C_MCF_PATH_TYPE_RUNTIME) {
kal_wsprintf(filename, "%s\\%s\0", MCF_FS_CUSTOM_FOLDER_PATH, apply_filename);
}
strncpy(apply_filename, MCF_FS_DEFAULT_INI_FILE_NAME, MCF_FILE_MAX_NAME_LEN - 1);
is_default_path = KAL_TRUE;
}
fs_api_ret[0] = MCF_FS_CMPT_Read(filename, &fs_cmpt);
if (fs_api_ret[0] < FS_NO_ERROR) {
MD_TRC_MCF_TR_READ_INI_FILE_FAIL(*apply_path_type, fs_api_ret[0]);
dhl_print_string(TRACE_INFO, DHL_USER_FLAG_NONE, MOD_MCF, apply_filename);
/* If cannot read given INI file, read default INI file */
if (is_default_path == KAL_FALSE) {
if (*apply_path_type == L4C_MCF_PATH_TYPE_OTA) {
kal_wsprintf(filename, "%s\\%s\0", MCF_FS_DEFAULT_FOLDER_PATH, apply_filename);
} else if (*apply_path_type == L4C_MCF_PATH_TYPE_RUNTIME) {
kal_wsprintf(filename, "%s\\%s\0", MCF_FS_CUSTOM_FOLDER_PATH, apply_filename);
}
strncpy(apply_filename, MCF_FS_DEFAULT_INI_FILE_NAME, MCF_FILE_MAX_NAME_LEN - 1);
fs_api_ret[0] = MCF_FS_CMPT_Read(filename, &fs_cmpt);
if (fs_api_ret[0] < FS_NO_ERROR) {
MD_TRC_MCF_TR_READ_INI_FILE_FAIL(*apply_path_type, fs_api_ret[0]);
dhl_print_string(TRACE_INFO, DHL_USER_FLAG_NONE, MOD_MCF, apply_filename);
ret = MCF_OTA_R_READ_INI_FILE_FAIL;
return ret;
}
} else {
ret = MCF_OTA_R_READ_INI_FILE_FAIL;
return ret;
}
}
if (file_size >= MCF_MAX_INI_FILE_SIZE-1) {
MD_TRC_MCF_TR_READ_INI_FILE_OVERSIZE(file_size, MCF_MAX_INI_FILE_SIZE);
ret = MCF_OTA_R_READ_INI_FILE_FAIL;
return ret;
}
/* Read file */
fs_cmpt.opid_map = NVRAM_FS_CMPT_OPEN | NVRAM_FS_CMPT_READ | NVRAM_FS_CMPT_CLOSE;
fs_cmpt.Flag = FS_READ_ONLY;
fs_cmpt.Length = file_size;
fs_cmpt.Offset = 0;
fs_cmpt.Whence = FS_FILE_BEGIN;
fs_cmpt.DataPtr = ini_file->buff;
fs_cmpt.Read = &read_byte;
fs_cmpt.FileSize = &dummy_para;
fs_api_ret[0] = MCF_FS_CMPT_Read(filename, &fs_cmpt);
if (fs_api_ret[0] < FS_NO_ERROR) {
MD_TRC_MCF_TR_READ_INI_FILE_FAIL(*apply_path_type, fs_api_ret[0]);
dhl_print_string(TRACE_INFO, DHL_USER_FLAG_NONE, MOD_MCF, apply_filename);
ret = MCF_OTA_R_READ_OTA_FILE_FAIL;
return ret;
}
if (file_size < MCF_MAX_INI_FILE_SIZE){
ini_file->buff[file_size] = '\0';
}
return ret;
}
kal_bool mcf_find_ini_item(kal_char* buff, kal_char *item, kal_char *value, mcf_t *pMcf)
{
kal_bool ret = KAL_TRUE;
kal_char *varstr = NULL, *substr = NULL;
kal_char *saveptr = NULL;
kal_char *item_ptr = NULL;
kal_char *item_tag = NULL;
mcf_ini_file_t *ini_file = &(pMcf->ini_file);
kal_char *buffer = (kal_char *)ini_file->tmp_buff;
//buff and item cannot be NULL
if(buff == NULL || item == NULL) {
MD_TRC_MCF_TR_FIND_INI_ITEM_ERROR_INPUT_NULL();
ret = KAL_FALSE;
return ret;
}
MD_TRC_MCF_TR_FIND_INI_ITEM_START(item);
/* Remove space and to uppercase */
mcf_remove_spaces_and_carrier_return(buff);
mcf_toupper(buff);
mcf_toupper(item);
mcf_remove_spaces_and_carrier_return(item);
kal_mem_set(buffer,0,MCF_MAX_INI_FILE_SIZE);
strncpy(buffer,buff,MCF_MAX_INI_FILE_SIZE-1);
buffer[MCF_MAX_INI_FILE_SIZE-1] = '\0';
item_ptr = strstr (buffer,item);
if (item_ptr != 0) {
item_tag = kal_strtok_r(item_ptr,"=",&saveptr);
substr = kal_strtok_r(NULL,"=",&saveptr);
if (item_tag != 0) {
if (strcmp(item_tag,item) == 0){
if (substr != NULL){
varstr = strstr(substr,"\n");
if (varstr == NULL){
if (strlen(substr) > MCF_MAX_INI_ITEM_VALUE_LEN-1){
memset(value, 0, MCF_MAX_INI_ITEM_VALUE_LEN);
strncpy(value, substr, MCF_MAX_INI_ITEM_VALUE_LEN);
}else{
memset(value, 0, MCF_MAX_INI_ITEM_VALUE_LEN);
strncpy(value, substr, strlen(substr));
}
}else{
if (strlen(substr)-strlen(varstr) + 1 > MCF_MAX_INI_ITEM_VALUE_LEN-1){
memset(value, 0, MCF_MAX_INI_ITEM_VALUE_LEN);
strncpy(value, substr, MCF_MAX_INI_ITEM_VALUE_LEN);
}else{
memset(value, 0, MCF_MAX_INI_ITEM_VALUE_LEN);
strncpy(value, substr, strlen(substr)-strlen(varstr));
}
}
}else{
value = NULL;
MD_TRC_MCF_TR_FIND_INI_ITEM_ERROR_CAN_NOT_FIND_ITEM();
ret = KAL_FALSE;
return ret;
}
}else{
value = NULL;
MD_TRC_MCF_TR_FIND_INI_ITEM_ERROR_ITEM_LENGTH();
ret = KAL_FALSE;
return ret;
}
} else {
value = NULL;
MD_TRC_MCF_TR_FIND_INI_ITEM_ERROR_CAN_NOT_FIND_ITEM();
ret = KAL_FALSE;
return ret;
}
} else {
value = NULL;
MD_TRC_MCF_TR_FIND_INI_ITEM_ERROR_CAN_NOT_FIND_ITEM();
ret = KAL_FALSE;
return ret;
}
MD_TRC_MCF_TR_FIND_INI_ITEM_RETURN_VALUE(item, value);
return ret;
}
kal_bool mcf_find_ini_sbp_id(kal_char *tag_str, kal_uint32 *sbp_id, kal_uint16 *sbp_id_num, kal_bool *general)
{
kal_uint16 i = 0;
kal_bool ret = KAL_TRUE;
kal_char *saveptr = NULL, *varstr = NULL, *substr = NULL, *tmpstr = NULL;
kal_char *sbp_id_tag[MCF_MAX_TAG_NUM];
kal_uint16 tag_cnt = 0;
kal_char *tag[MCF_MAX_TAG_NUM];
kal_uint16 tag_num = 0;
MD_TRC_MCF_TR_FIND_INI_SBP_ID_START(tag_str);
//buff and item cannot be NULL
if(tag_str == NULL) {
MD_TRC_MCF_TR_FIND_INI_SBP_ID_ERROR_INPUT_NULL();
ret = KAL_FALSE;
return ret;
}
//Split ',' from tag
substr = kal_strtok_r(tag_str, ",", &saveptr);
if (substr == NULL){
MD_TRC_MCF_TR_FIND_INI_SBP_ID_ERROR_CAN_NOT_FIND_ITEM();
ret = KAL_FALSE;
return ret;
}
while(substr != NULL){
tag[tag_cnt] = substr;
tag_cnt++;
substr = kal_strtok_r(NULL, ",",&saveptr);
}
/* ICCID case should apply general tlvota*/
tmpstr = strstr(tag[0], "_");
if (tmpstr == NULL){
*general = KAL_TRUE;
MD_TRC_MCF_TR_FIND_INI_SBP_ID_ICCID_USIR(tag[0]);
}
//Split '_' from SBPID_MNC_MCC tag
sbp_id_tag[0] = kal_strtok_r(tag[0], "_", &saveptr);
if (strcmp(sbp_id_tag[0],"") == 0){
MD_TRC_MCF_TR_FIND_INI_SBP_ID_ERROR_CAN_NOT_FIND_ITEM();
}
/* NA case should apply general tlvota */
if (strcmp(sbp_id_tag[0],"NA") == 0){
*general = KAL_TRUE;
MD_TRC_MCF_TR_FIND_INI_SBP_ID_NA(*general);
}
for (i = 1; i < tag_cnt; i++){
tmpstr = strstr(tag[i], "_");
if (tmpstr == NULL){
*general = KAL_TRUE;
if(i+1 < tag_cnt){
i++;
}
}else{
varstr = kal_strtok_r(tag[i], "_",&saveptr);
if(varstr == NULL){
*general = KAL_TRUE;
if(i+1 < tag_cnt){
i++;
}
}else{
if(strcmp(varstr,"NA") == 0){
*general = KAL_TRUE;
if(i+1 < tag_cnt){
i++;
}
}
if (strcmp(varstr,sbp_id_tag[tag_num]) != 0){
//save different sbp_id
tag_num++;
sbp_id_tag[tag_num] = varstr;
}
}
}
}
for (i = 0; i < tag_num + 1; i++){
sbp_id[i] = mcf_atoi(sbp_id_tag[i]);
}
*sbp_id_num = tag_num + 1;
MD_TRC_MCF_TR_FIND_INI_SBP_ID_RETURN_NUM(*sbp_id_num);
return ret;
}
kal_bool mcf_compose_ini_item(kal_char *orig_buff, kal_char *new_buff, kal_char *item, kal_char *orig_value, kal_char *value)
{
kal_bool ret = KAL_TRUE;
kal_char *tmpstr = NULL, *varstr = NULL, *substr = NULL;
kal_uint32 len = 0;
MD_TRC_MCF_TR_COMPOSE_INI_ITEM_START(item, orig_value);
mcf_remove_spaces_and_carrier_return(orig_buff);
mcf_remove_spaces_and_carrier_return(item);
kal_mem_set(new_buff, 0, MCF_MAX_INI_FILE_SIZE);
substr = strstr (orig_buff,"\0");
if (substr != NULL){
len = strlen(orig_buff);
}else{
MD_TRC_MCF_TR_COMPOSE_INI_ITEM_INVALID_BUFF();
ret = KAL_FALSE;
return ret;
}
substr = strstr (orig_buff,item);
if (substr != NULL){
varstr = strstr(substr,"=");
if (varstr != NULL){
if (strlen(substr)-strlen(varstr) == strlen(item)){
if(strcmp(orig_value,"") != 0){
tmpstr = strstr(substr,orig_value);
if (tmpstr != NULL){
if ((len-strlen(varstr)+4+strlen(value)+strlen(tmpstr)-strlen(orig_value)) >= MCF_MAX_INI_FILE_SIZE){
MD_TRC_MCF_TR_COMPOSE_INI_ITEM_INVALID_BUFF_LENGTH();
ret = KAL_FALSE;
return ret;
}
strncpy(new_buff,orig_buff,len-strlen(varstr));
strncat (new_buff,"=", MCF_MAX_INI_FILE_SIZE - 1);
strncat (new_buff,value, MCF_MAX_INI_FILE_SIZE - 1);
strncat (new_buff,tmpstr+strlen(orig_value), MCF_MAX_INI_FILE_SIZE - 1);
strncat (new_buff,"\n\0", MCF_MAX_INI_FILE_SIZE - 1);
}else{
MD_TRC_MCF_TR_COMPOSE_INI_ITEM_INVALID_ORIGINAL_VALUE(orig_value);
ret = KAL_FALSE;
return ret;
}
}else{
if ((len-strlen(varstr)+4+strlen(value)+strlen(substr)-strlen(item)) >= MCF_MAX_INI_FILE_SIZE){
MD_TRC_MCF_TR_COMPOSE_INI_ITEM_INVALID_BUFF_LENGTH();
ret = KAL_FALSE;
return ret;
}
strncpy(new_buff,orig_buff,len-strlen(varstr));
strncat (new_buff,"=", MCF_MAX_INI_FILE_SIZE - 1);
strncat (new_buff,value, MCF_MAX_INI_FILE_SIZE - 1);
strncat (new_buff,"\n", MCF_MAX_INI_FILE_SIZE - 1);
strncat (new_buff,substr+strlen(item)+1, MCF_MAX_INI_FILE_SIZE - 1);
strncat (new_buff,"\n\0", MCF_MAX_INI_FILE_SIZE - 1);
}
}else{
MD_TRC_MCF_TR_COMPOSE_INI_ITEM_ERROR_ITEM_LENGTH();
ret = KAL_FALSE;
return ret;
}
}else{
tmpstr = strstr(substr,orig_value);
if (tmpstr != NULL){
if ((len+4+strlen(value)+strlen(tmpstr)-strlen(orig_value)) >= MCF_MAX_INI_FILE_SIZE){
MD_TRC_MCF_TR_COMPOSE_INI_ITEM_INVALID_BUFF_LENGTH();
ret = KAL_FALSE;
return ret;
}
strncpy(new_buff,orig_buff,len);
strncat (new_buff,"=", MCF_MAX_INI_FILE_SIZE - 1);
strncat (new_buff,value, MCF_MAX_INI_FILE_SIZE - 1);
strncat (new_buff,tmpstr+strlen(orig_value), MCF_MAX_INI_FILE_SIZE - 1);
strncat (new_buff,"\n\0", MCF_MAX_INI_FILE_SIZE - 1);
}else{
MD_TRC_MCF_TR_COMPOSE_INI_ITEM_INVALID_ORIGINAL_VALUE(orig_value);
ret = KAL_FALSE;
return ret;
}
}
}
else{
//new item
if ((len+5+strlen(item)+strlen(value)) >= MCF_MAX_INI_FILE_SIZE){
MD_TRC_MCF_TR_COMPOSE_INI_ITEM_INVALID_BUFF_LENGTH();
ret = KAL_FALSE;
return ret;
}
strncpy(new_buff,orig_buff, MCF_MAX_INI_FILE_SIZE - 1);
strncat(new_buff,"\n", MCF_MAX_INI_FILE_SIZE - 1);
strncat(new_buff,item, MCF_MAX_INI_FILE_SIZE - 1);
strncat(new_buff,"=", MCF_MAX_INI_FILE_SIZE - 1);
strncat(new_buff,value, MCF_MAX_INI_FILE_SIZE - 1);
strncat (new_buff,"\n\0", MCF_MAX_INI_FILE_SIZE - 1);
}
return ret;
}
void mcf_dump_data(kal_bool is_booting, void *p_data, kal_uint32 len)
{
kal_uint32 i = 0;
kal_uint32 buff;
for (i = 0; len > 0; i++){
if (len >= 4) {
buff = 0;
kal_mem_cpy(&buff, (kal_uint8 *)p_data + (i * 4), 4);
len -= 4;
} else {
buff = 0;
kal_mem_cpy(&buff, (kal_uint8 *)p_data + (i * 4), len);
len = 0;
}
if (is_booting == KAL_TRUE) {
MCF_BOOT_TRACE(MCF_BOOT_TR_DATA_DUMP_TRACE, i, buff);
}
MD_TRC_MCF_TR_DATA_DUMP_TRACE(i, buff);
}
}
#define GUARD_PARRTEN 0xAABBCCDD
#define FULL_PARRTEN 0xAABBFFFF
void mcf_write_boot_trace(kal_uint32 trace_enum, ...)
{
va_list ap;
kal_uint32 i = 0;
kal_uint32 *value= NULL;
char *substr = NULL;
// store into com_Mcf.boot_trace_buff
// enum, num, type, size, value, type, size, value
// enum, num, type, size, value, type, size, value
// enum, num, type, size, value, type, size, value
mcf_boot_trace_struct *trace_ptr = (mcf_boot_trace_struct *)com_Mcf.boot_trace_buff_ptr;
mcf_boot_trace_value_struct *value_ptr = NULL;
if(com_Mcf.boot_trace_buff_ptr == NULL ){
com_Mcf.boot_trace_buff_ptr = (kal_uint32 *)com_Mcf.boot_trace_buff;
trace_ptr = (mcf_boot_trace_struct *)com_Mcf.boot_trace_buff_ptr;
}
value_ptr = &trace_ptr->value_ptr;
if((char *)trace_ptr + 512 > (char *)com_Mcf.boot_trace_buff + sizeof(com_Mcf.boot_trace_buff))
{
if(com_Mcf.boot_trace_full == 1) return;
com_Mcf.boot_trace_full = 1;
trace_ptr->guard_pattern = GUARD_PARRTEN;
trace_ptr->trace_enum = FULL_PARRTEN;
com_Mcf.boot_trace_buff_ptr = (kal_uint32 *)(trace_ptr+1);
return;
}
trace_ptr->guard_pattern = GUARD_PARRTEN;
trace_ptr->trace_enum = trace_enum;
substr = strstr(boot_trace_format[trace_enum].log_format, "%");
va_start(ap, trace_enum);
while ( (kal_uint32)(value = (kal_uint32 *)va_arg(ap,void *)) != END_PATTERN)
{
if(substr == NULL) break;
switch(*(substr + 1))
{
case 's':
{
char *string_ptr = (char *)value;
value_ptr->size = strlen(string_ptr);
kal_mem_cpy(&value_ptr->type_u.string, string_ptr, value_ptr->size + 1);
value_ptr->size = ((value_ptr->size + 4) >> 2 ) << 2 ; // size pedding to 4 byte alignment
value_ptr->type = MCF_TYPE_STRING;
}
break;
default:
{
value_ptr->size = sizeof(kal_uint32);
value_ptr->type_u.integer = (kal_uint32)value;
value_ptr->type = MCF_TYPE_INTEGER;
}
break;
}
i++;
value_ptr = (mcf_boot_trace_value_struct *)((kal_uint8 *)&value_ptr->type_u.value + value_ptr->size);
substr = strstr(substr + 1, "%");
}
va_end(ap);
trace_ptr->total_num = i;
if(trace_ptr->total_num == 0 ) com_Mcf.boot_trace_buff_ptr = (kal_uint32 *)(trace_ptr+1);
else com_Mcf.boot_trace_buff_ptr = (kal_uint32 *)value_ptr;
}
void mcf_dump_boot_trace(void)
{
mcf_boot_trace_struct *trace_ptr = (mcf_boot_trace_struct *)com_Mcf.boot_trace_buff;
kal_uint32 i = 0;
mcf_boot_trace_value_struct value_list[7]; // max DHL arg is 7
mcf_boot_trace_value_struct *current_value;
while ((char *)trace_ptr < (char *)com_Mcf.boot_trace_buff_ptr)
{
ASSERT(trace_ptr->guard_pattern == GUARD_PARRTEN);
current_value = &trace_ptr->value_ptr;
if(trace_ptr->trace_enum == FULL_PARRTEN)
{
MCF_BOOT_PRINT("[MCF] boot trace buffer full!!!");
break;
}
for(i = 0 ; i < trace_ptr->total_num ; i++)
{
value_list[i].size = current_value->size;
switch(current_value->type)
{
case MCF_TYPE_INTEGER:
value_list[i].type_u.value = current_value->type_u.integer;
break;
case MCF_TYPE_STRING:
value_list[i].type_u.value = (kal_uint32)&current_value->type_u.string;
break;
default:
break;
}
current_value = (mcf_boot_trace_value_struct *)((kal_uint8 *)&current_value->type_u.value + current_value->size);
}
switch(trace_ptr->total_num)
{
case 0:
MCF_BOOT_PRINT(boot_trace_format[trace_ptr->trace_enum].log_format);
break;
case 1:
MCF_BOOT_PRINT(boot_trace_format[trace_ptr->trace_enum].log_format, value_list[0].type_u.value);
break;
case 2:
MCF_BOOT_PRINT(boot_trace_format[trace_ptr->trace_enum].log_format, value_list[0].type_u.value, value_list[1].type_u.value);
break;
case 3:
MCF_BOOT_PRINT(boot_trace_format[trace_ptr->trace_enum].log_format, value_list[0].type_u.value, value_list[1].type_u.value, value_list[2].type_u.value);
break;
case 4:
MCF_BOOT_PRINT(boot_trace_format[trace_ptr->trace_enum].log_format, value_list[0].type_u.value, value_list[1].type_u.value, value_list[2].type_u.value, value_list[3].type_u.value);
break;
case 5:
MCF_BOOT_PRINT(boot_trace_format[trace_ptr->trace_enum].log_format, value_list[0].type_u.value, value_list[1].type_u.value, value_list[2].type_u.value, value_list[3].type_u.value, value_list[4].type_u.value);
break;
case 6:
MCF_BOOT_PRINT(boot_trace_format[trace_ptr->trace_enum].log_format, value_list[0].type_u.value, value_list[1].type_u.value, value_list[2].type_u.value, value_list[3].type_u.value, value_list[4].type_u.value, value_list[5].type_u.value);
break;
case 7:
MCF_BOOT_PRINT(boot_trace_format[trace_ptr->trace_enum].log_format, value_list[0].type_u.value, value_list[1].type_u.value, value_list[2].type_u.value, value_list[3].type_u.value, value_list[4].type_u.value, value_list[5].type_u.value, value_list[6].type_u.value);
break;
}
if(trace_ptr->total_num == 0) trace_ptr++;
else trace_ptr = (mcf_boot_trace_struct *)current_value;
}
}
mcf_ota_result_e mcf_write_buffer(
kal_char *folder_path,
kal_char *file_name,
kal_uint8 *buffer,
kal_uint32 total_size)
{
mcf_ota_result_e mcf_ret = MCF_OTA_R_SUCCESS;
#if defined(__MTK_TARGET__)
kal_wchar file_path_name[MCF_FILE_MAX_MD_PATH_LEN * 2];
FS_HANDLE file_handle;
kal_uint32 len = 0;
kal_int32 ret = FS_NO_ERROR;
MD_TRC_MCF_TR_WRITE_BUFFER_START(file_name, folder_path, total_size);
kal_wsprintf(file_path_name, "%s\\%s\0", folder_path, file_name);
file_handle = FS_Open(file_path_name, FS_CREATE | FS_READ_WRITE | FS_OPEN_NO_DIR);
ret = FS_Write(file_handle, buffer, total_size, &len);
if (ret != FS_NO_ERROR) {
MD_TRC_MCF_TR_WRITE_BUFFER_FAIL(file_handle, ret);
mcf_ret = MCF_OTA_R_WRITE_DISK_FAIL;
}
FS_Close(file_handle);
#endif
return mcf_ret;
}
mcf_ota_result_e mcf_get_file_last_mod_time(
kal_char *apply_filename,
l4c_mcf_path_type_enum apply_path_type,
kal_uint64 *last_mod_time)
{
mcf_ota_result_e mcf_ret = MCF_OTA_R_SUCCESS;
kal_wchar filename[MCF_FILE_MAX_MD_PATH_LEN + MCF_FILE_MAX_NAME_LEN];
FS_FileDetail fs_file_detail[L4C_MCF_PATH_TYPE_MAX] = {0};
kal_int32 fs_api_ret[L4C_MCF_PATH_TYPE_MAX];
MD_TRC_MCF_TR_GET_FILE_LAST_MOD_TIME_START(apply_filename, apply_path_type);
if (apply_path_type == L4C_MCF_PATH_TYPE_OTA){
kal_wsprintf(filename, "%s\\%s\0", MCF_FS_DEFAULT_FOLDER_PATH, apply_filename);
}else if(apply_path_type == L4C_MCF_PATH_TYPE_RUNTIME){
kal_wsprintf(filename, "%s\\%s\0", MCF_FS_CUSTOM_FOLDER_PATH, apply_filename);
}else{
*last_mod_time = 0;
MD_TRC_MCF_TR_GET_FILE_LAST_MOD_TIME_INVALID_PATH_TYPE(apply_path_type);
mcf_ret = MCF_OTA_R_INVALID_PARAMETER;
return mcf_ret;
}
fs_api_ret[apply_path_type] = FS_GetFileDetail(filename, &fs_file_detail[apply_path_type]);
MD_TRC_MCF_TR_GET_FILE_LAST_MOD_TIME(apply_path_type, fs_api_ret[apply_path_type],
(kal_uint32)((fs_file_detail[apply_path_type].LastStatusChangeTime >> 32) & 0xFFFFFFFF), (kal_uint32)(fs_file_detail[apply_path_type].LastStatusChangeTime & 0xFFFFFFFF));
if (fs_api_ret[apply_path_type] == FS_NO_ERROR) {
*last_mod_time = fs_file_detail[apply_path_type].LastStatusChangeTime;
} else {
*last_mod_time = 0;
MD_TRC_MCF_TR_GET_FILE_LAST_MOD_TIME_FAIL(L4C_MCF_PATH_TYPE_OTA, fs_api_ret[L4C_MCF_PATH_TYPE_OTA]);
mcf_ret = MCF_OTA_R_READ_OTA_FILE_FAIL;
return mcf_ret;
}
return mcf_ret;
}
void mcf_dump_important_info(void)
{
mcf_t *pMcf = mcf_get_instance();
mcf_ota_file_t *ota_file = &(pMcf->ota_file);
mcf_tlvota_file_t *tlvota_file;
kal_uint8 path_type;
kal_char relative_path_name[MCF_FILE_MAX_NAME_LEN];
kal_uint8 i = 0;
MCF_R_LOCK_OBJECT(ota_file, mcf_enhmutex_g);
if (ota_file) {
path_type = ota_file->path_type;
strncpy(relative_path_name, ota_file->relative_path_name, MCF_FILE_MAX_NAME_LEN - 1);
MD_TRC_MCF_TR_DUMP_IMPORTANT_INFO_OTA_FILE(path_type, relative_path_name);
MCF_R_UNLOCK_OBJECT(ota_file, mcf_enhmutex_g);
} else {
MD_TRC_MCF_TR_DUMP_IMPORTANT_INFO_TAKE_READ_LOCK_FAIL();
}
for (i = 0; i < MAX_SIM_NUM; i++) {
tlvota_file = &(pMcf->tlvota_file[i]);
MCF_R_LOCK_OBJECT(tlvota_file, mcf_enhmutex_g);
if (tlvota_file) {
path_type = tlvota_file->path_type;
strncpy(relative_path_name, tlvota_file->relative_path_name, MCF_FILE_MAX_NAME_LEN - 1);
MD_TRC_MCF_TR_DUMP_IMPORTANT_INFO_TLVOTA_FILE(i, path_type, relative_path_name);
MCF_R_UNLOCK_OBJECT(tlvota_file, mcf_enhmutex_g);
} else {
MD_TRC_MCF_TR_DUMP_IMPORTANT_INFO_TAKE_READ_LOCK_FAIL();
}
}
tlvota_file = &(pMcf->general_tlvota_file);
MCF_R_LOCK_OBJECT(tlvota_file, mcf_enhmutex_g);
if (tlvota_file) {
path_type = tlvota_file->path_type;
strncpy(relative_path_name, tlvota_file->relative_path_name, MCF_FILE_MAX_NAME_LEN - 1);
MD_TRC_MCF_TR_DUMP_IMPORTANT_INFO_GENERAL_TLVOTA_FILE(path_type, relative_path_name);
MCF_R_UNLOCK_OBJECT(tlvota_file, mcf_enhmutex_g);
} else {
MD_TRC_MCF_TR_DUMP_IMPORTANT_INFO_TAKE_READ_LOCK_FAIL();
}
}
kal_int32 mcf_atoi(const void *src)
{
kal_int32 res=0;
kal_int8 *p_src=(kal_int8*)src;
while( *p_src>='0' && *p_src<='9' ){
res = res*10 + (*p_src - '0');
p_src++;
}
return res;
}
kal_int32 mcf_str_strcmp(const void *str1, const void *str2)
{
kal_int8 *p_str1=(kal_int8*)str1, *p_str2=(kal_int8*)str2;
if( p_str1==NULL || p_str2==NULL ){
return 1;
}
while(*p_str1==*p_str2 && *p_str1!='\0'){
p_str1++;
p_str2++;
}
return *p_str1 - *p_str2;
}
void mcf_remove_spaces_and_carrier_return(kal_char* src)
{
kal_char* str1 = src;
kal_char* str2 = src;
while(*str2 != 0)
{
*str1 = *str2++;
/* 32 = space, 13 = "\r" */
/* Windows uses \r\n to a new line, Linux uses \n to a new line */
if(*str1 != 32 && *str1 != 13){
str1++;
}
}
*str1 = 0;
}
void mcf_toupper(kal_char* src)
{
kal_uint32 k = 0;
while(src[k] != 0)
{
if(src[k] >= 'a' && src[k] <= 'z'){
src[k] = src[k]-32;
}
k++;
}
}
kal_int32 mcf_str_strlen(const void *src)
{
kal_int8 *p_src=(kal_int8*)src;
kal_int32 len=0;
if( p_src==NULL ){
return 0;
}
while('\0' != *p_src){
len++;
p_src++;
}
return len;
}
kal_bool mcf_hex_str_reverse(kal_char *str, kal_uint32 length)
{
kal_char temp1;
kal_char temp2;
kal_uint32 i;
if(str == NULL || length < 0 || length %2 != 0){
return KAL_FALSE;
}
if(length < 4){
return KAL_TRUE;
}
for(i = 0; i < length/2; i+=2){
temp1 = str[i];
str[i] = str[length-2-i];
str[length-2-i] = temp1;
temp2 = str[i+1];
str[i+1] = str[length-1-i];
str[length-1-i] = temp2;
}
return KAL_TRUE;
}
kal_int16 mcf_binary_search_lid(kal_uint16 find_lid, kal_uint16 *lid_arr, kal_uint16 lid_size, kal_uint16 *new_pos)
{
kal_int16 first = 0, // First array element
last = lid_size - 1, // Last array element
middle = 0, // Mid point of search
position = -1; // Position of search value
kal_bool found = KAL_FALSE; // Flag
while (!found && first <= last)
{
middle = (first + last) / 2; // Calculate mid point
if(middle < 0)
return -1;
if (lid_arr[middle] == find_lid) // If value is found at mid
{
found = KAL_TRUE;
position = middle;
}
else if (lid_arr[middle] > find_lid){ // If value is in lower half
last = middle - 1;
*new_pos = middle;
}
else{
first = middle + 1; // If value is in upper half
*new_pos = first;
}
}
if(lid_size == 0){
*new_pos = 0;
}
return position;
}
kal_bool mcf_insert_lid(kal_uint16 new_lid, kal_uint16 *lid_arr, kal_uint16 lid_size, kal_uint16 new_pos)
{
kal_bool ret = KAL_TRUE;
kal_uint16 i = 0;
if (lid_size >= NVRAM_MCF_SAVE_LAST_LID_CNT){
ret = KAL_FALSE;
return ret;
}
for(i = lid_size; i > new_pos; i--){
lid_arr[i] = lid_arr[i-1];
}
lid_arr[new_pos] = new_lid;
return ret;
}
#ifdef __MCF_COMBINE_FILE_SUPPORT__
kal_int16 mcf_binary_search_lid_struct(kal_uint16 find_lid, nvram_mcf_lid_config_struct *lid_conf, kal_uint16 lid_size, kal_uint16 *new_pos)
{
kal_int16 first = 0, // First array element
last = lid_size - 1, // Last array element
middle = 0, // Mid point of search
position = -1; // Position of search value
kal_bool found = KAL_FALSE; // Flag
while (!found && first <= last)
{
middle = (first + last) / 2; // Calculate mid point
if(middle < 0)
return -1;
if (lid_conf[middle].lid == find_lid) // If value is found at mid
{
found = KAL_TRUE;
position = middle;
}
else if (lid_conf[middle].lid > find_lid){ // If value is in lower half
last = middle - 1;
*new_pos = middle;
}
else{
first = middle + 1; // If value is in upper half
*new_pos = first;
}
}
if(lid_size == 0){
*new_pos = 0;
}
return position;
}
kal_bool mcf_insert_lid_struct(kal_uint16 new_lid, nvram_mcf_lid_config_struct *lid_conf, kal_uint16 lid_size, kal_uint16 new_pos, kal_bool not_reset, kal_bool set_combined)
{
kal_bool ret = KAL_TRUE;
kal_uint16 i = 0;
if (lid_size >= NVRAM_MCF_SAVE_LAST_LID_CNT){
ret = KAL_FALSE;
return ret;
}
for(i = lid_size; i > new_pos; i--){
kal_mem_cpy(&lid_conf[i], &lid_conf[i-1], sizeof(nvram_mcf_lid_config_struct));
}
lid_conf[new_pos].lid = new_lid;
lid_conf[new_pos].not_reset = not_reset;
lid_conf[new_pos].set_combined = set_combined;
return ret;
}
kal_bool mcf_clear_last_modified_lid(nvram_mcf_lid_config_struct *lid_conf, kal_uint16 *lid_size)
{
kal_bool ret = KAL_TRUE;
kal_uint16 i = 0;
kal_uint16 index = 0;
kal_uint16 lid_cnt = 0;
kal_uint16 total_cnt = 0;
lid_cnt = *lid_size;
if (lid_cnt >= NVRAM_MCF_SAVE_LAST_LID_CNT){
ret = KAL_FALSE;
return ret;
}
for(i = 0; i < lid_cnt; i++){
if(lid_conf[i].set_combined == KAL_TRUE ){
kal_mem_set(&lid_conf[i], 0, sizeof(nvram_mcf_lid_config_struct));
index++;
while(index < lid_cnt && lid_conf[index].set_combined == KAL_TRUE){
kal_mem_set(&lid_conf[index], 0, sizeof(nvram_mcf_lid_config_struct));
index++;
}
}
if (index < lid_cnt && i != index){
kal_mem_cpy(&lid_conf[i], &lid_conf[index], sizeof(nvram_mcf_lid_config_struct));
kal_mem_set(&lid_conf[index], 0, sizeof(nvram_mcf_lid_config_struct));
total_cnt++;
}else if(i == index){
total_cnt++;
}
index ++;
}
*lid_size = total_cnt;
return ret;
}
#endif
kal_int8* mcf_bytes_to_hex(const void *bytes, kal_int32 length, kal_bool upperCase, void *hex)
{
kal_int8 *p_hex=(kal_int8*)hex, *p_bytes=(kal_int8*)bytes;
kal_int8 LCaseHexArray[] = "0123456789abcdef";
kal_int8 UCaseHexArray[] = "0123456789ABCDEF";
kal_uint32 i=0, v=0;
kal_mem_set(p_hex, 0, length*2 + 1);
if (p_bytes == NULL) {
return NULL;
}
for (i=0; i<length; i++) {
v=p_bytes[i]&0xFF;
if( v<0 || (v>>4)>=sizeof(LCaseHexArray) || (v&0x0F)>=sizeof(LCaseHexArray) || (v>>4) < 0 || (v&0x0F) < 0){
return NULL;
} else if( upperCase ){
p_hex[i*2] = UCaseHexArray[v >> 4];
p_hex[i*2 + 1] = UCaseHexArray[v & 0x0F];
} else{
p_hex[i*2] = LCaseHexArray[v >> 4];
p_hex[i*2 + 1] = LCaseHexArray[v & 0x0F];
}
}
return p_hex;
}
kal_int8* mcf_hex_to_bytes(const void *hex, kal_int32 *length, void *bytes)
{
kal_int8 *p_hex=(kal_int8*)hex, *p_bytes=(kal_int8*)bytes;
kal_int32 len_hex=mcf_str_strlen(p_hex), i=0, j=0;
kal_int8 temp[2];
//EXT_ASSERT(len_hex%2==0, len_hex, bytes, 0);
if( len_hex%2==1 || len_hex<0 ){
return NULL;
}
kal_mem_set(p_bytes, 0, len_hex / 2);
*length = 0;
for( i=0; i<(len_hex/2); i++ ) {
temp[0] = p_hex[i * 2];
temp[1] = p_hex[i * 2 + 1];
for (j=0; j<2; j++) {
if (temp[j] >= 'A' && temp[j] <= 'F') {
temp[j] = temp[j] - 'A' + 10;
} else if (temp[j] >= 'a' && temp[j] <= 'f') {
temp[j] = temp[j] - 'a' + 10;
} else if (temp[j] >= '0' && temp[j] <= '9') {
temp[j] = temp[j] - '0';
} else {
return NULL;
}
}
p_bytes[i] = (temp[0]<<4) | temp[1];
}
*length = len_hex / 2;
return p_bytes;
}
void mcf_replace_char(kal_char* src, kal_char old_ch, kal_char new_ch)
{
kal_uint32 k = 0;
while(src[k] != 0)
{
if(src[k] == old_ch){
src[k] = new_ch;
}
k++;
}
}
void mcf_snprintf(kal_char * str, size_t num, const char * fmt, ...)
{
kal_int32 ret_snprintf = 0;
va_list arglist;
va_start(arglist, fmt);
ret_snprintf = vsnprintf(str, num, fmt, arglist);
va_end(arglist);
if (ret_snprintf < 0 || ret_snprintf > num){
strncpy(str, "unknown error", num - 1);
MD_TRC_MCF_TR_MCF_SNPRINTF_FAIL(num, ret_snprintf);
}
}
#ifdef __MCF_FIND_TAG_SUPPORT__
extern MCF_DB_LID_MAPPING mcf_db_lid_mapping_tbl[];
extern MCF_DB_STRUCT_IDX mcf_db_struct_idx_tbl[];
kal_int32 mcf_parser_binary_search_struct_list(char *find_string, MCF_DB_STRUCT_VARIABLE const *struct_ptr, kal_uint32 struct_size)
{
kal_int32 first = 0, // First array element
last = struct_size - 1, // Last array element
middle, // Mid point of search
position = -1; // Position of search value
kal_bool found = KAL_FALSE; // Flag
while (!found && first <= last)
{
middle = (first + last) / 2; // Calculate mid point
if(middle < 0)
return -1;
if (mcf_str_strcmp(struct_ptr[middle].variable_name, find_string) == 0) // If value is found at mid
{
found = KAL_TRUE;
position = middle;
}
else if (mcf_str_strcmp(struct_ptr[middle].variable_name, find_string) > 0) // If value is in lower half
last = middle - 1;
else
first = middle + 1; // If value is in upper half
}
return position;
}
#endif
kal_bool mcf_find_tag_offset(
kal_uint32 lid_num,
char *tag_name,
kal_uint16 *byte_offset,
kal_uint16 *bit_offset,
kal_uint32 *size,
MCF_DB_STRUCT_VARIABLE const **var_ptr,
mcf_tag_info_struct *tag_ptr)
{
#ifdef __MCF_FIND_TAG_SUPPORT__
kal_uint16 i = 0;
kal_uint16 array_size_cnt = 1;
kal_int32 lid_idx = -1, struct_idx = -1;
char *saveptr = NULL, *saveptr2 = NULL, *varstr = NULL, *substr = NULL;
char var_name[MAX_VAR_LEN] = {0};
kal_bool next_is_bit = KAL_FALSE;
kal_uint32 start_time = GET_CURRENT_TIME();
if(tag_name == NULL || byte_offset == NULL || bit_offset == NULL || size == NULL)
{
MD_TRC_MCF_TR_FIND_TAG_ERROR_INPUT_NULL();
return KAL_FALSE;
}
*byte_offset = 0;
*bit_offset = 0;
*size= 0;
dhl_print_string(TRACE_INFO, DHL_USER_FLAG_NONE, MOD_MCF, tag_name);
for(i = 0 ; i < MCF_LID_MAPPING_TBL_SIZE ; i++)
{
if(mcf_db_lid_mapping_tbl[i].lid_num == lid_num)
{
lid_idx = i;
struct_idx = mcf_db_lid_mapping_tbl[i].struct_idx;
break;
}
}
// can not find this lid_num in mcf_db_lid_mapping_tbl
if(lid_idx == -1 || struct_idx > MCF_STRUCT_LIST_TBL_SIZE)
{
MD_TRC_MCF_TR_FIND_TAG_ERROR_CAN_NOT_FIND_LID_NUM(lid_num, struct_idx);
return KAL_FALSE;
}
// split "." for each variable
substr = kal_strtok_r(tag_name, ".", &saveptr);
while (substr){
kal_int32 pos = -1;
MCF_DB_STRUCT_VARIABLE const *var_struct_ptr = NULL;
// split "[" for get array num
varstr = kal_strtok_r(substr, "[", &saveptr2);
if(next_is_bit == KAL_TRUE){
kal_uint32 len = strlen(var_name);
var_name[len] = '.';
strcpy(var_name + len + 1, varstr);
}
else
{
strcpy(var_name, varstr);
}
var_struct_ptr = mcf_db_struct_idx_tbl[struct_idx].struct_ptr;
pos = mcf_parser_binary_search_struct_list(var_name, var_struct_ptr, mcf_db_struct_idx_tbl[struct_idx].struct_size);
if(pos == -1)
{
MCF_BOOT_TRACE(MCF_BOOT_TR_FIND_TAG_ERROR_CAN_NOT_FIND_TAG);
MD_TRC_MCF_TR_FIND_TAG_ERROR_CAN_NOT_FIND_TAG();
dhl_print_string(TRACE_ERROR, DHL_USER_FLAG_NONE, MOD_MCF, var_name);
return KAL_FALSE;
}
// get array size
if(next_is_bit == KAL_TRUE)
{
*bit_offset += var_struct_ptr[pos].bit_offset;
*size = var_struct_ptr[pos].total_size;
}
else
{
kal_uint32 array_size;
kal_uint8 i = 0;
tag_ptr->arr_cnt = 0;
*byte_offset += var_struct_ptr[pos].byte_offset;
*size = var_struct_ptr[pos].variable_size;
varstr = kal_strtok_r(NULL, "[", &saveptr2);
if(varstr != NULL){
do{
kal_uint8 j = 0;
kal_uint32 n = 1;
array_size = mcf_atoi(varstr);
j = i+1;
while(var_struct_ptr[pos].array_size[j] != 0)
{
n *= (var_struct_ptr[pos].array_size[j]);
j++;
array_size_cnt++;
}
i++;
*byte_offset += (array_size * n * var_struct_ptr[pos].variable_size);
tag_ptr->array_size[tag_ptr->arr_cnt] = array_size;
tag_ptr->arr_cnt++;
}while((varstr = kal_strtok_r(NULL, "[", &saveptr2)) != NULL);
if (i > array_size_cnt){
MD_TRC_MCF_TR_FIND_TAG_ERROR_OVER_SIZE(i, array_size_cnt);
dhl_print_string(TRACE_ERROR, DHL_USER_FLAG_NONE, MOD_MCF, var_name);
return KAL_FALSE;
}
}
else{
*size = var_struct_ptr[pos].total_size;
}
}
if(var_struct_ptr[pos].is_bit)
{
next_is_bit = KAL_TRUE;
tag_ptr->is_bit = KAL_TRUE;
tag_ptr->upper_vsize = var_struct_ptr[pos].variable_size;
}
if(var_struct_ptr[pos].struct_idx != -1)
{
struct_idx = var_struct_ptr[pos].struct_idx;
}
substr = kal_strtok_r(NULL, ".", &saveptr);
if (substr != 0){
tag_ptr->arr_cnt = 0;
kal_mem_set(tag_ptr->array_size, 0, 5);
}
*var_ptr = &var_struct_ptr[pos];
};
MD_TRC_MCF_TR_FIND_TAG_RETURN_VALUE(lid_num, *byte_offset, *bit_offset, *size, CALCULATE_LETENCY_DURATION(start_time, GET_CURRENT_TIME()));
return KAL_TRUE;
#else
return KAL_FALSE;
#endif
}
#ifdef __MCF_FIND_GID_SUPPORT__
extern MCF_DB_GID_LIST_STRUCT MCF_DB_GID_LIST[];
extern MCF_DB_GID_FORMULA_STRUCT MCF_DB_FORMULA_LIST[];
kal_int32 mcf_gid_binary_search_gid_list(kal_uint32 gid)
{
kal_int32 first = 0, // First array element
last = MCF_MAX_GID_LIST_SIZE - 1, // Last array element
middle, // Mid point of search
position = -1; // Position of search value
kal_bool found = KAL_FALSE; // Flag
while (!found && first <= last)
{
middle = (first + last) / 2; // Calculate mid point
if(middle < 0)
return -1;
if (gid == MCF_DB_GID_LIST[middle].gid) // If value is found at mid
{
found = KAL_TRUE;
position = middle;
}
else if (gid < MCF_DB_GID_LIST[middle].gid) // If value is in lower half
last = middle - 1;
else
first = middle + 1; // If value is in upper half
}
return position;
}
kal_int32 mcf_gid_binary_search_gid_formula_list(kal_uint32 gid)
{
kal_int32 first = 0, // First array element
last = MCF_MAX_GID_FORMULA_LIST_SIZE - 1, // Last array element
middle, // Mid point of search
position = -1; // Position of search value
kal_bool found = KAL_FALSE; // Flag
while (!found && first <= last)
{
middle = (first + last) / 2; // Calculate mid point
if(middle < 0)
return -1;
if (gid == MCF_DB_FORMULA_LIST[middle].gid) // If value is found at mid
{
found = KAL_TRUE;
position = middle;
}
else if (gid < MCF_DB_FORMULA_LIST[middle].gid) // If value is in lower half
last = middle - 1;
else
first = middle + 1; // If value is in upper half
}
return position;
}
#endif
kal_bool mcf_find_gid_offset(
kal_uint32 gid,
char *array_idx_string,
kal_uint16 *lid_num,
kal_uint16 *byte_offset,
kal_uint16 *bit_offset,
kal_uint32 *size,
kal_bool *is_bit
)
{
#ifdef __MCF_FIND_GID_SUPPORT__
kal_int32 gid_list_pos = 0, gid_formula_list_pos = 0;
kal_uint32 start_time = GET_CURRENT_TIME();
if(byte_offset == NULL || bit_offset == NULL || size == NULL || is_bit == NULL || array_idx_string == NULL)
{
MD_TRC_MCF_TR_FIND_GID_ERROR_INPUT_NULL();
return KAL_FALSE;
}
MD_TRC_MCF_TR_FIND_GID_START(gid, array_idx_string);
gid_list_pos = mcf_gid_binary_search_gid_list(gid);
if(gid_list_pos == -1 || gid_list_pos < 0)
{
MCF_BOOT_TRACE(MCF_BOOT_TR_FIND_GID_ERROR_CAN_NOT_FIND_GID, gid);
MD_TRC_MCF_TR_FIND_GID_ERROR_CAN_NOT_FIND_GID(gid);
return KAL_FALSE;
}
*lid_num = MCF_DB_GID_LIST[gid_list_pos].lid_num;
*size = MCF_DB_GID_LIST[gid_list_pos].variable_size;
*is_bit = MCF_DB_GID_LIST[gid_list_pos].is_bit;
*bit_offset = MCF_DB_GID_LIST[gid_list_pos].bit_offset;
if(MCF_DB_GID_LIST[gid_list_pos].array_formula == KAL_FALSE)
{
*byte_offset = MCF_DB_GID_LIST[gid_list_pos].byte_offset;
}
else
{
kal_int32 array_size[10] = {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1};
kal_uint32 i = 0, j = 0;
kal_uint32 current_array_i = 0;
char *saveptr = NULL, *saveptr2 = NULL, *varstr = NULL, *substr = NULL;
char gid_formula_string[MCF_MAX_FORMULA_LEN] = {0};
char temp_array_idx[64] = {0};
*byte_offset = 0;
strncpy(temp_array_idx, array_idx_string, 63);
temp_array_idx[63] = '\0';
// parsing array_idx_string
varstr = kal_strtok_r(temp_array_idx, "$", &saveptr);
if(varstr != NULL){
do{
array_size[i++] = mcf_atoi(varstr);
if(i >= 10)
{
MCF_BOOT_TRACE(MCF_BOOT_TR_FIND_GID_ERROR_FORMULA_OUT_OF_BOUND , gid);
MD_TRC_MCF_TR_FIND_GID_ERROR_FORMULA_OUT_OF_BOUND(gid);
dhl_print_string(TRACE_ERROR, DHL_USER_FLAG_NONE, MOD_MCF, temp_array_idx);
return KAL_FALSE;
}
}while((varstr = kal_strtok_r(NULL, "$", &saveptr)) != NULL);
}
gid_formula_list_pos = mcf_gid_binary_search_gid_formula_list(gid);
if(gid_formula_list_pos == -1 || gid_formula_list_pos < 0)
{
MCF_BOOT_TRACE(MCF_BOOT_TR_FIND_GID_ERROR_CAN_NOT_FIND_FORMULA, gid);
MD_TRC_MCF_TR_FIND_GID_ERROR_CAN_NOT_FIND_FORMULA(gid);
return KAL_FALSE;
}
//[5](0,164)+[8](4,20)+[5](0,4)+0
//[10](0,12)+2+2
//[2,8,2](4,2)
strncpy(gid_formula_string, MCF_DB_FORMULA_LIST[gid_formula_list_pos].byte_offset_formula, MCF_MAX_FORMULA_LEN - 1);
substr = kal_strtok_r(gid_formula_string, "+", &saveptr);
if(substr != NULL){
do{
kal_int32 max_array_idx[5] = {-1,-1,-1,-1,-1};
kal_uint32 local_base = 0, local_size = 0, base = 0;
kal_uint32 max_array_i = 0;
kal_bool max_array_start = KAL_FALSE, local_start = KAL_FALSE, base_start = KAL_TRUE;
char temp[20] = {0};
j = 0;
while(substr[j] != '\0')
{
if(substr[j] == '['){
max_array_start = KAL_TRUE; local_start = KAL_FALSE; base_start = KAL_FALSE;
kal_mem_set(temp, 0, 20);
i = 0;
}
else if(substr[j] == ']'){
max_array_start = KAL_FALSE; local_start = KAL_FALSE; base_start = KAL_FALSE;
varstr = kal_strtok_r(temp, ",", &saveptr2);
if(varstr != NULL){
do{
max_array_idx[max_array_i++] = mcf_atoi(varstr);
}while((varstr = kal_strtok_r(NULL, ",", &saveptr2)) != NULL);
}
}
else if(substr[j] == '('){
max_array_start = KAL_FALSE; local_start = KAL_TRUE; base_start = KAL_FALSE;
kal_mem_set(temp, 0, 20);
i = 0;
}
else if(substr[j] == ')'){
max_array_start = KAL_FALSE; local_start = KAL_FALSE; base_start = KAL_FALSE;
varstr = kal_strtok_r(temp, ",", &saveptr2);
if (varstr != NULL){
local_base = mcf_atoi(varstr);
}
varstr = kal_strtok_r(NULL, ",", &saveptr2);
if (varstr != NULL){
local_size = mcf_atoi(varstr);
}
}
else // digit
{
// get max array idx
if(max_array_start == KAL_TRUE)
{
temp[i++] = substr[j];
}
else if(local_start == KAL_TRUE)
{
temp[i++] = substr[j];
}
else if(base_start == KAL_TRUE)
{
base = mcf_atoi(substr);
}
}
j++;
}
{
kal_uint32 temp_offset = 0;
for(i = 0; i< max_array_i; i++)
{
kal_uint32 array_idx = array_size[current_array_i++];
kal_uint32 array_offset = 0;
if(array_idx == -1) break;
array_offset = array_idx * local_size;
if(array_idx >= max_array_idx[i])
{
return KAL_FALSE; // array size error
}
for(j = i + 1 ; j < 5 ; j++)
{
if(max_array_idx[j] == -1) break;
array_offset *= max_array_idx[j];
}
temp_offset += array_offset;
}
*byte_offset += temp_offset + local_base;
}
*byte_offset += base;
}while((substr = kal_strtok_r(NULL, "+", &saveptr)) != NULL);
}
}
MD_TRC_MCF_TR_FIND_GID_RETURN_VALUE(*lid_num, *byte_offset, *bit_offset, *size, *is_bit, CALCULATE_LETENCY_DURATION(start_time, GET_CURRENT_TIME()));
return KAL_TRUE;
#else
return KAL_FALSE;
#endif
}
kal_uint16 mcf_find_gid_return_lid_num(kal_uint32 gid)
{
#ifdef __MCF_FIND_GID_SUPPORT__
kal_int32 gid_list_pos = 0;
gid_list_pos = mcf_gid_binary_search_gid_list(gid);
if(gid_list_pos == -1 || gid_list_pos < 0)
{
MCF_BOOT_TRACE(MCF_BOOT_TR_FIND_GID_RETURN_LID_NUM_ERROR_CAN_NOT_FIND_GID, gid);
MD_TRC_MCF_TR_FIND_GID_RETURN_LID_NUM_ERROR_CAN_NOT_FIND_GID(gid);
return -1; // not found
}
return MCF_DB_GID_LIST[gid_list_pos].lid_num;
#else
return -1;
#endif
}
kal_uint32 mcf_calc_check_sum(kal_uint32 *ptr, kal_uint32 len)
{
kal_uint32 check_sum = 0, i = 0;
for(i = 0; i< (len/sizeof(kal_uint32)) ; i++, ptr++)
check_sum += *ptr;
check_sum = ~check_sum + 1;
return check_sum;
}
kal_uint32 mcf_check_check_sum(kal_uint32 *ptr, kal_uint32 len)
{
kal_uint32 check_sum = 0, i = 0;
for(i = 0; i< (len/sizeof(kal_uint32)) ; i++, ptr++)
check_sum += *ptr;
if(check_sum != 0)
MD_TRC_MCF_TR_CHECKSUM_ERROR(check_sum);
return check_sum;
}
// password will be auto padding to 16B
// content should be padding to 16B alignment
// conrent length should be mod by 16
kal_bool mcf_encrypt_128bit(char *password, char *content, kal_uint32 content_length)
{
kal_uint8 iv[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
kal_uint8 copy_len = 0;
kal_uint32 output_len;
t_cust_chl_sym_key key;
AES_PARAM aes_param;
kal_uint32 ret = CUST_CHL_ERROR_NONE;
kal_uint32 start_time = ust_get_current_time();
if(content == NULL) return KAL_FALSE;
if(content_length % 16 != 0) return KAL_FALSE;
copy_len = strlen(password);
if(copy_len > 16) copy_len = 16;
key.m_key_len = 16;
kal_mem_set(key.m_key, 0, sizeof(key.m_key));
kal_mem_cpy(&key.m_key, password, copy_len);
aes_param.IVLength = 16;
aes_param.IV = iv;
ret = CustCHL_AES_Encrypt_data(CUST_CHL_ALG_AES128, CUST_CHL_MODE_CBC, content_length, (kal_uint8 *)content, &output_len, (kal_uint8 *)content, &key, &aes_param);
MD_TRC_MCF_TR_ENCRYPT(ust_us_duration(start_time, ust_get_current_time()));
if (ret != CUST_CHL_ERROR_NONE)
return KAL_FALSE;
return KAL_TRUE;
}
// password will be auto padding to 16B
// content should be padding to 16B alignment
// conrent length should be mod by 16
kal_bool mcf_decrypt_128bit(char *password, char *content, kal_uint32 content_length)
{
kal_uint8 iv[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
kal_uint8 copy_len = 0;
kal_uint32 output_len;
t_cust_chl_sym_key key;
AES_PARAM aes_param;
kal_uint32 ret = CUST_CHL_ERROR_NONE;
kal_uint32 start_time = ust_get_current_time();
if(content == NULL) return KAL_FALSE;
if(content_length % 16 != 0) return KAL_FALSE;
copy_len = strlen(password);
if(copy_len > 16) copy_len = 16;
key.m_key_len = 16;
kal_mem_set(key.m_key, 0, sizeof(key.m_key));
kal_mem_cpy(&key.m_key, password, copy_len);
aes_param.IVLength = 16;
aes_param.IV = iv;
ret = CustCHL_AES_Decrypt_data(CUST_CHL_ALG_AES128, CUST_CHL_MODE_CBC, content_length, (kal_uint8 *)content, &output_len, (kal_uint8 *)content, &key, &aes_param);
MD_TRC_MCF_TR_DECRYPT(ust_us_duration(start_time, ust_get_current_time()));
if (ret != CUST_CHL_ERROR_NONE)
return KAL_FALSE;
return KAL_TRUE;
}
#ifdef __MCF_COMBINE_FILE_SUPPORT__
void mcf_merge_insert_node(mcf_merge_link_list_struct *pre_node, mcf_merge_link_list_struct *next_node, mcf_merge_link_list_struct *insert_node, void *insert_data)
{
if(pre_node != NULL) pre_node->next_node = insert_node;
if(next_node != NULL) next_node->pre_node = insert_node;
insert_node->pre_node = pre_node;
insert_node->next_node = next_node;
insert_node->data = insert_data;
MD_TRC_MCF_TR_MERGE_LINK_LIST_INSERT_NODE_INFO((pre_node != NULL)?(kal_uint32)pre_node->next_node : 0,
(next_node != NULL)?(kal_uint32)next_node->pre_node : 0,
(kal_uint32)insert_node->pre_node, (kal_uint32)insert_node->next_node);
}
// comparison sequence : LID => RID => GID => array idx
kal_int8 mcf_merge_compare_ota_data(mcf_tool_gid_ota_file_item_t *first_data, mcf_tool_gid_ota_file_item_t *second_data)
{
kal_uint16 first_lid_num = mcf_find_gid_return_lid_num(first_data->global_id);
kal_uint16 second_lid_num = mcf_find_gid_return_lid_num(second_data->global_id);
kal_int32 array_cmp_result = 0;
MD_TRC_MCF_TR_MERGE_CMP_OTA_DATA_INFO(first_lid_num, first_data->record_idx, first_data->global_id, second_lid_num, second_data->record_idx, second_data->global_id);
if(first_lid_num < second_lid_num) return -1;
else if (first_lid_num > second_lid_num) return 1;
if(first_data->record_idx < second_data->record_idx) return -1;
else if (first_data->record_idx > second_data->record_idx) return 1;
if(first_data->global_id < second_data->global_id) return -1;
else if (first_data->global_id > second_data->global_id) return 1;
if (first_data->array_index_len > 0)
{
array_cmp_result= strncmp(&(first_data->buff_start), &(second_data->buff_start), first_data->array_index_len);
MD_TRC_MCF_TR_MERGE_CMP_OTA_DATA_ARRAY_INFO(array_cmp_result);
if (array_cmp_result < 0) return -1;
if (array_cmp_result > 0) return 1;
}
return 0;
}
kal_int8 mcf_merge_compare_ota_by_op_tag(char *tag1, char *tag2)
{
kal_uint16 tag1_sbpid= 0, tag1_mcc=0, tag1_mnc=0, tag2_sbpid=0, tag2_mcc=0, tag2_mnc=0; // use 0 as "NA"
kal_char sbp_id_tag[MCF_MAX_TAG_NUM] = {0};
const char *delim = "_";
char * pch;
kal_char *saveptr = NULL;
// parsing tag1
strncpy(sbp_id_tag, tag1, MCF_MAX_TAG_NUM-1);
pch = kal_strtok_r(sbp_id_tag, delim, &saveptr);
if (pch != NULL && strcmp(pch, "NA") != 0) tag1_sbpid = mcf_atoi(pch);
pch = kal_strtok_r(NULL, delim, &saveptr);
if (pch != NULL && strcmp(pch, "NA") != 0) tag1_mcc = mcf_atoi(pch);
pch = kal_strtok_r(NULL, delim, &saveptr);
if (pch != NULL && strcmp(pch, "NA") != 0) tag1_mnc = mcf_atoi(pch);
// parsing tag2
strncpy(sbp_id_tag, tag2, MCF_MAX_TAG_NUM-1);
pch = kal_strtok_r(sbp_id_tag, delim, &saveptr);
if (pch != NULL && strcmp(pch, "NA") != 0) tag2_sbpid = mcf_atoi(pch);
pch = kal_strtok_r(NULL, delim, &saveptr);
if (pch != NULL && strcmp(pch, "NA") != 0) tag2_mcc = mcf_atoi(pch);
pch = kal_strtok_r(NULL, delim, &saveptr);
if (pch != NULL && strcmp(pch, "NA") != 0) tag2_mnc = mcf_atoi(pch);
// comparion
// SBP
if ((tag1_sbpid == tag2_sbpid) && (tag1_mcc == tag2_mcc) && (tag1_mnc == tag2_mnc))
return 0;
else if (tag1_sbpid > tag2_sbpid)
return 1;
else if (tag1_sbpid < tag2_sbpid)
return -1;
else
{
// SBP is equal, then compare MCC
if (tag1_mcc > tag2_mcc) return 1;
else if (tag1_mcc < tag2_mcc) return -1;
else
{
// SBP and MCC are equal, then compare MNC
if (tag1_mnc > tag2_mnc) return 1;
else if (tag1_mnc < tag2_mnc) return -1;
}
}
return 0;
}
// comparison sequence : LID => TAG type=> TAG => GID => array idx
kal_int8 mcf_merge_compare_ota_by_op_data(mcf_tool_gid_tlvota_file_item_t *first_data, mcf_tool_gid_tlvota_file_item_t *second_data)
{
kal_uint16 first_lid_num = mcf_find_gid_return_lid_num(first_data->global_id);
kal_uint16 second_lid_num = mcf_find_gid_return_lid_num(second_data->global_id);
kal_int32 array_cmp_result = 0;
MD_TRC_MCF_TR_MERGE_CMP_OTA_DATA_INFO(first_lid_num, first_data->tag_type, first_data->global_id, second_lid_num, second_data->tag_type, second_data->global_id);
if(first_lid_num < second_lid_num) return -1;
else if (first_lid_num > second_lid_num) return 1;
if(first_data->tag_type < second_data->tag_type) return -1;
else if (first_data->tag_type > second_data->tag_type) return 1;
{
kal_char sbp_tag1[MCF_FILE_MAX_TAG_LEN] = {0};
kal_char sbp_tag2[MCF_FILE_MAX_TAG_LEN] = {0};
kal_int8 result= 0;
strncpy(sbp_tag1, &(first_data->buff_start) , first_data->tag_len);
strncpy(sbp_tag2, &(second_data->buff_start) , second_data->tag_len);
result= mcf_merge_compare_ota_by_op_tag(sbp_tag1, sbp_tag2);
if(result < 0) return -1;
if(result > 0) return 1;
}
if(first_data->global_id < second_data->global_id) return -1;
else if (first_data->global_id > second_data->global_id) return 1;
if (first_data->array_index_len > 0)
{
array_cmp_result = strncmp(&(first_data->buff_start) + first_data->tag_len, &(second_data->buff_start) + second_data->tag_len, first_data->array_index_len);
MD_TRC_MCF_TR_MERGE_CMP_OTA_DATA_ARRAY_INFO(array_cmp_result);
if (array_cmp_result < 0) return -1;
if (array_cmp_result > 0) return 1;
}
return 0;
}
// sort by ascending
mcf_merge_link_list_struct * mcf_merge_link_list_insert(mcf_merge_link_list_struct *head, mcf_merge_link_list_struct *tail, mcf_merge_link_list_struct *current, void *insert_data, mcf_ota_type_enum type)
{
mcf_merge_link_list_struct *current_node = head->next_node;
mcf_merge_link_list_struct *new_node = NULL;
kal_int8 result = 0;
if (type == MCF_TYPE_OTA) MD_TRC_MCF_TR_MERGE_LINK_LIST_INSERT_DATA_START(((mcf_tool_gid_ota_file_item_t *)insert_data)->global_id);
else if (type == MCF_TYPE_OTA_BY_OP) MD_TRC_MCF_TR_MERGE_LINK_LIST_INSERT_DATA_START(((mcf_tool_gid_tlvota_file_item_t *)insert_data)->global_id);
if (current != NULL)
{
// quick determine
if (type == MCF_TYPE_OTA)
{
result = mcf_merge_compare_ota_data((mcf_tool_gid_ota_file_item_t *)insert_data, (mcf_tool_gid_ota_file_item_t *)current->data);
}
else if (type == MCF_TYPE_OTA_BY_OP)
{
result = mcf_merge_compare_ota_by_op_data((mcf_tool_gid_tlvota_file_item_t *)insert_data, (mcf_tool_gid_tlvota_file_item_t *)current->data);
}
else
{
DEBUG_ASSERT(0);
return NULL;
}
MD_TRC_MCF_TR_MERGE_LINK_LIST_INSERT_CMP_RESULT(result);
// if insert data >= current, then start from current.
// if insert data < current, back to head to find again.
if (result == 1 || result == 0) {
current_node = current;
MD_TRC_MCF_TR_MERGE_LINK_LIST_USE_CURRENT_AS_START();
}
else {
current_node = head->next_node;
MD_TRC_MCF_TR_MERGE_LINK_LIST_USE_HEAD_AS_START();
}
}
while (current_node != tail)
{
// ========= COMPARE NODE =========
result = 0;
if (type == MCF_TYPE_OTA)
{
result = mcf_merge_compare_ota_data((mcf_tool_gid_ota_file_item_t *)insert_data, (mcf_tool_gid_ota_file_item_t *)current_node->data);
}
else if (type == MCF_TYPE_OTA_BY_OP)
{
result = mcf_merge_compare_ota_by_op_data((mcf_tool_gid_tlvota_file_item_t *)insert_data, (mcf_tool_gid_tlvota_file_item_t *)current_node->data);
}
else
{
DEBUG_ASSERT(0);
return NULL;
}
MD_TRC_MCF_TR_MERGE_LINK_LIST_INSERT_CMP_RESULT(result);
// ========= INSERT NODE =========
// insert data should be inserted BEFORE current node
if (result == -1)
{
new_node = mcf_malloc(sizeof(mcf_merge_link_list_struct));
if(new_node == NULL) return NULL;
MD_TRC_MCF_TR_MERGE_OTA_BUFFER_ALLOCATE((kal_uint32)new_node);
kal_mem_set(new_node, 0, sizeof(mcf_merge_link_list_struct));
mcf_merge_insert_node(current_node->pre_node, current_node, new_node, insert_data);
return current_node->pre_node;
}
// insert data should be REPLACED current node
else if (result == 0)
{
current_node->data = insert_data;
return current_node;
}
// insert data should be inserted AFTER current node
else if (result == 1)
{
// due to the link list is acending, skip
}
else
DEBUG_ASSERT(0);
current_node = current_node->next_node;
}
// insert the last
new_node = mcf_malloc(sizeof(mcf_merge_link_list_struct));
if(new_node == NULL) return NULL;
MD_TRC_MCF_TR_MERGE_OTA_BUFFER_ALLOCATE((kal_uint32)new_node);
kal_mem_set(new_node, 0, sizeof(mcf_merge_link_list_struct));
mcf_merge_insert_node(current_node->pre_node, current_node, new_node, insert_data);
return current_node->pre_node;
}
void mcf_merge_link_list_free(mcf_merge_link_list_struct *head)
{
mcf_merge_link_list_struct *current = head;
while (current != NULL)
{
mcf_merge_link_list_struct *next = current->next_node;
MD_TRC_MCF_TR_MERGE_OTA_BUFFER_FREE((kal_uint32)current);
mcf_free(current);
current = next;
}
}
kal_bool mcf_merge_read_buffer_to_linklist(void *buffer, mcf_merge_link_list_struct *head, mcf_merge_link_list_struct *tail, mcf_ota_type_enum type)
{
mcf_tool_file_info_t *file_header = (mcf_tool_file_info_t *)buffer;
kal_uint32 item_cnt = 0;
mcf_merge_link_list_struct *current = NULL;
if (type == MCF_TYPE_OTA) {
mcf_tool_gid_ota_file_item_t *current_data = (mcf_tool_gid_ota_file_item_t *)((kal_uint8 *)file_header + file_header->total_len);
MD_TRC_MCF_TR_MERGE_READ_BUFFER_TO_LINKLIST_TOTAL_ITEM(file_header->item_num);
for (item_cnt = 0 ; item_cnt < file_header->item_num ; item_cnt ++)
{
current = mcf_merge_link_list_insert(head, tail, current, current_data, type);
if(current == NULL) return KAL_FALSE;
MD_TRC_MCF_TR_MERGE_READ_BUFFER_TO_LINKLIST_ITEM_INFO(item_cnt, current_data->global_id);
current_data = (mcf_tool_gid_ota_file_item_t *)((kal_uint8 *)current_data + current_data->total_len);
}
}
else if (type == MCF_TYPE_OTA_BY_OP)
{
mcf_tool_gid_tlvota_file_item_t *current_data = (mcf_tool_gid_tlvota_file_item_t *)((kal_uint8 *)file_header + file_header->total_len);
MD_TRC_MCF_TR_MERGE_READ_BUFFER_TO_LINKLIST_TOTAL_ITEM(file_header->item_num);
for (item_cnt = 0 ; item_cnt < file_header->item_num ; item_cnt ++)
{
current = mcf_merge_link_list_insert(head, tail, current, current_data, type);
if(current == NULL) return KAL_FALSE;
MD_TRC_MCF_TR_MERGE_READ_BUFFER_TO_LINKLIST_ITEM_INFO(item_cnt, current_data->global_id);
current_data = (mcf_tool_gid_tlvota_file_item_t *)((kal_uint8 *)current_data + current_data->total_len);
}
}
else
{
DEBUG_ASSERT(0);
return KAL_FALSE;
}
return KAL_TRUE;
}
void mcf_merge_make_ota_file_header(mcf_tool_file_info_t *output_header, mcf_tool_file_info_t *copy_header)
{
kal_char sw_version[MCF_SW_VERNO_LEN] = {0};
kal_char gen_time[MCF_FILE_MAX_GEN_TIME_LEN] = {0};
struct tm current_time;
#if defined(__MTK_TARGET__) && defined(__SUPPORT_CLIB_TIME__)
time_t currenttime;
kal_mem_set(&current_time, 0, sizeof(struct tm));
if (time(&currenttime) != -1)
localtime_r(&currenttime, &current_time);
#else
current_time.tm_year = 118;
current_time.tm_mon = 0;
current_time.tm_mday = 1;
current_time.tm_hour = 0;
current_time.tm_min = 0;
current_time.tm_sec = 0;
#endif
MD_TRC_MCF_TR_MERGE_MAKE_OTA_FILE_HEADER_START();
kal_mem_set(output_header, 0, sizeof(mcf_tool_file_info_t));
kal_mem_set(sw_version, 0, sizeof(kal_char) * MCF_SW_VERNO_LEN);
kal_mem_set(gen_time, 0, sizeof(kal_char) * MCF_FILE_MAX_GEN_TIME_LEN);
if(sprintf(gen_time,"%04d.%02d%02d.%02d%02d%02d", current_time.tm_year + 1900, current_time.tm_mon + 1, current_time.tm_mday, current_time.tm_hour, current_time.tm_min, current_time.tm_sec) <0)
DEBUG_ASSERT(0);
strncpy(sw_version, release_verno(), MCF_SW_VERNO_LEN-1);
output_header->sw_version_len = strlen(sw_version);
output_header->gen_time_len = strlen(gen_time);
output_header->file_version = copy_header->file_version;
output_header->operation_mask = copy_header->operation_mask;
if((output_header->operation_mask & MCF_FILE_OP_SHA256_RSA2048) || (output_header->operation_mask & MCF_FILE_OP_SHA384_RSA3072))
{
output_header->operation_mask &= ~(MCF_FILE_OP_SHA256_RSA2048);
output_header->operation_mask &= ~(MCF_FILE_OP_SHA384_RSA3072);
}
strcpy(output_header->file_type, copy_header->file_type);
// copy header
{
// use copy_len to prevent out of array
kal_uint32 copy_len = 0;
if (output_header->sw_version_len >= MCF_SW_VERNO_LEN -1) copy_len = MCF_SW_VERNO_LEN -1;
else copy_len = output_header->sw_version_len;
strncpy(&output_header->buff_start, sw_version, copy_len);
if (output_header->gen_time_len >= MCF_FILE_MAX_GEN_TIME_LEN -1) copy_len = MCF_FILE_MAX_GEN_TIME_LEN -1;
else copy_len = output_header->gen_time_len;
strncpy(&output_header->buff_start + output_header->sw_version_len, gen_time, copy_len);
}
output_header->total_len = (kal_uint32)&output_header->buff_start + output_header->sw_version_len + output_header->gen_time_len - (kal_uint32)output_header; // end addr - start addr
if ((output_header->total_len % 4) != 0)
output_header->total_len += 4 - (output_header->total_len % 4); // 4 bytes alignment
MD_TRC_MCF_TR_MERGE_MAKE_OTA_FILE_HEADER_END();
}
// if first buffer has same gid, it will be replaced by second_buffer
kal_bool mcf_merge_ota_buffer(void *first_buffer, void *second_buffer, void *output_buffer, kal_uint32 output_buffer_size)
{
mcf_merge_link_list_struct *head, *tail;
mcf_ota_type_enum type = 0;
kal_bool ret = KAL_FALSE;
kal_uint32 coreID = kal_get_current_core_id();
MD_TRC_MCF_TR_MERGE_OTA_BUFFER_START();
MD_TRC_MCF_TR_MERGE_OTA_BUFFER_MCF_CORE(coreID);
//If MCF is running on Core0, need to wake up Core1 to run other task
if (coreID == 0){
SleepDrv_LockSleep( SLEEP_CTL_MCF, CORE1);
MD_TRC_MCF_TR_MERGE_OTA_BUFFER_LOCK_CORE(CORE1, coreID);
}
if (first_buffer == NULL || second_buffer == NULL || output_buffer == NULL) {
MD_TRC_MCF_TR_MERGE_OTA_BUFFER_INPUT_PARAM_ERROR((kal_uint32)first_buffer, (kal_uint32)second_buffer, (kal_uint32)output_buffer);
if (coreID == 0){
SleepDrv_UnlockSleep( SLEEP_CTL_MCF, CORE1);
MD_TRC_MCF_TR_MERGE_OTA_BUFFER_UNLOCK_CORE(CORE1, coreID);
}
return KAL_FALSE;
}
// head init
head = mcf_malloc(sizeof(mcf_merge_link_list_struct));
tail = mcf_malloc(sizeof(mcf_merge_link_list_struct));
if(head == NULL || tail == NULL){
if (coreID == 0){
SleepDrv_UnlockSleep( SLEEP_CTL_MCF, CORE1);
MD_TRC_MCF_TR_MERGE_OTA_BUFFER_UNLOCK_CORE(CORE1, coreID);
}
return KAL_FALSE;
}
kal_mem_set(head, 0, sizeof(mcf_merge_link_list_struct));
kal_mem_set(tail, 0, sizeof(mcf_merge_link_list_struct));
head->next_node = tail;
tail->pre_node = head;
MD_TRC_MCF_TR_MERGE_OTA_BUFFER_ALLOCATE_HEAD_TAIL((kal_uint32)head, (kal_uint32)tail);
// ========== read first buffer ==========
{
mcf_tool_file_info_t *file_header = (mcf_tool_file_info_t *)first_buffer;
if (strcmp(file_header->file_type, MCF_FILE_TYPE_OTA) == 0) type = MCF_TYPE_OTA;
else if (strcmp(file_header->file_type, MCF_FILE_TYPE_TLVOTA) == 0) type = MCF_TYPE_OTA_BY_OP;
else{
DEBUG_ASSERT(0);
if (coreID == 0){
SleepDrv_UnlockSleep( SLEEP_CTL_MCF, CORE1);
MD_TRC_MCF_TR_MERGE_OTA_BUFFER_UNLOCK_CORE(CORE1, coreID);
}
return KAL_FALSE;
}
MD_TRC_MCF_TR_MERGE_OTA_BUFFER_FIRST_BUFFER_TYPE(type);
ret = mcf_merge_read_buffer_to_linklist(first_buffer, head, tail, type);
if(ret == KAL_FALSE){
if (coreID == 0){
SleepDrv_UnlockSleep( SLEEP_CTL_MCF, CORE1);
MD_TRC_MCF_TR_MERGE_OTA_BUFFER_UNLOCK_CORE(CORE1, coreID);
}
return KAL_FALSE;
}
}
// ========== read second buffer ==========
{
mcf_tool_file_info_t *file_header = (mcf_tool_file_info_t *)second_buffer;
if (strcmp(file_header->file_type, MCF_FILE_TYPE_OTA) == 0) type = MCF_TYPE_OTA;
else if (strcmp(file_header->file_type, MCF_FILE_TYPE_TLVOTA) == 0) type = MCF_TYPE_OTA_BY_OP;
else{
DEBUG_ASSERT(0);
if (coreID == 0){
SleepDrv_UnlockSleep( SLEEP_CTL_MCF, CORE1);
MD_TRC_MCF_TR_MERGE_OTA_BUFFER_UNLOCK_CORE(CORE1, coreID);
}
return KAL_FALSE;
}
MD_TRC_MCF_TR_MERGE_OTA_BUFFER_SECOND_BUFFER_TYPE(type);
ret = mcf_merge_read_buffer_to_linklist(second_buffer, head, tail, type);
if(ret == KAL_FALSE){
if (coreID == 0){
SleepDrv_UnlockSleep( SLEEP_CTL_MCF, CORE1);
MD_TRC_MCF_TR_MERGE_OTA_BUFFER_UNLOCK_CORE(CORE1, coreID);
}
return KAL_FALSE;
}
}
// ========== output buffer ==========
{
mcf_tool_file_info_t *copy_header = (mcf_tool_file_info_t *)second_buffer;
mcf_tool_file_info_t *output_header = (mcf_tool_file_info_t *)output_buffer;
kal_uint8 *current_pos = NULL;
mcf_merge_link_list_struct *current_node = head->next_node;
mcf_merge_make_ota_file_header(output_header, copy_header); // copy first header to output header
current_pos = (kal_uint8 *)output_header + output_header->total_len;
if (strcmp(output_header->file_type, MCF_FILE_TYPE_OTA) == 0) type = MCF_TYPE_OTA;
else if (strcmp(output_header->file_type, MCF_FILE_TYPE_TLVOTA) == 0) type = MCF_TYPE_OTA_BY_OP;
else{
DEBUG_ASSERT(0);
if (coreID == 0){
SleepDrv_UnlockSleep( SLEEP_CTL_MCF, CORE1);
MD_TRC_MCF_TR_MERGE_OTA_BUFFER_UNLOCK_CORE(CORE1, coreID);
}
return KAL_FALSE;
}
while (current_node != tail)
{
if (type == MCF_TYPE_OTA)
{
mcf_tool_gid_ota_file_item_t *current_ota_data = current_node->data;
kal_mem_cpy(current_pos, current_ota_data, current_ota_data->total_len);
current_pos += current_ota_data->total_len;
MD_TRC_MCF_TR_MERGE_OTA_BUFFER_OUTPUT_GID(current_ota_data->global_id);
mcf_dump_data(KAL_FALSE, &current_ota_data->buff_start + current_ota_data->array_index_len, current_ota_data->value_len);
}
else if (type == MCF_TYPE_OTA_BY_OP)
{
mcf_tool_gid_tlvota_file_item_t *current_ota_by_data = current_node->data;
kal_mem_cpy(current_pos, current_ota_by_data, current_ota_by_data->total_len);
current_pos += current_ota_by_data->total_len;
MD_TRC_MCF_TR_MERGE_OTA_BUFFER_OUTPUT_GID(current_ota_by_data->global_id);
mcf_dump_data(KAL_FALSE, &current_ota_by_data->buff_start + current_ota_by_data->tag_len + current_ota_by_data->array_index_len, current_ota_by_data->value_len);
}
current_node = current_node->next_node;
output_header->item_num++;
output_header->file_size = (kal_uint32)((kal_uint8 *)current_pos - (kal_uint8 *)output_header);
if (output_header->file_size > output_buffer_size)
{
MD_TRC_MCF_TR_MERGE_OTA_BUFFER_OUTPUT_BUFFER_OUT_OF_SIZE(output_header->file_size, output_buffer_size);
if (coreID == 0){
SleepDrv_UnlockSleep( SLEEP_CTL_MCF, CORE1);
MD_TRC_MCF_TR_MERGE_OTA_BUFFER_UNLOCK_CORE(CORE1, coreID);
}
return KAL_FALSE;
}
}
if ((output_header->operation_mask & MCF_FILE_OP_AES_128) || (output_header->operation_mask & MCF_FILE_OP_AES_256))
{
if (((output_header->file_size - output_header->total_len) % 16) != 0)
output_header->file_size += 16 - (output_header->file_size - output_header->total_len) % 16; // content should be 16 bytes alignment
}
else if (((output_header->file_size - output_header->total_len) % 4) != 0)
{
output_header->file_size += 4 - (output_header->file_size - output_header->total_len) % 4; // content should be 4 bytes alignment
}
}
// ========== security ==========
{
mcf_tool_file_info_t *file_header = (mcf_tool_file_info_t *)output_buffer;
// checksum
if (file_header->operation_mask & MCF_FILE_OP_CHECKSUM)
{
file_header->checksum = 0;
file_header->checksum = mcf_calc_check_sum((kal_uint32 *)output_buffer, file_header->file_size);
}
// encrypt
if (file_header->operation_mask & MCF_FILE_OP_AES_128)
{
kal_char password[MCF_MAX_PASSWORD_LEN] = {0};
mcf_get_custom_aes_password(password);
if (mcf_encrypt_128bit(password, (kal_char *)((kal_uint8 *)file_header + file_header->total_len), (file_header->file_size - file_header->total_len)) == KAL_FALSE)
{
if (coreID == 0){
SleepDrv_UnlockSleep( SLEEP_CTL_MCF, CORE1);
MD_TRC_MCF_TR_MERGE_OTA_BUFFER_UNLOCK_CORE(CORE1, coreID);
}
return KAL_FALSE;
}
}
else if (file_header->operation_mask & MCF_FILE_OP_AES_256)
{
kal_char password[MCF_MAX_PASSWORD_LEN] = {0};
mcf_get_custom_aes_password(password);
if (mcf_encrypt_256bit(password, (kal_char *)((kal_uint8 *)file_header + file_header->total_len), (file_header->file_size - file_header->total_len)) == KAL_FALSE)
{
if (coreID == 0){
SleepDrv_UnlockSleep( SLEEP_CTL_MCF, CORE1);
MD_TRC_MCF_TR_MERGE_OTA_BUFFER_UNLOCK_CORE(CORE1, coreID);
}
return KAL_FALSE;
}
}
}
mcf_merge_link_list_free(head);
MD_TRC_MCF_TR_MERGE_OTA_BUFFER_END();
if (coreID == 0){
SleepDrv_UnlockSleep( SLEEP_CTL_MCF, CORE1);
MD_TRC_MCF_TR_MERGE_OTA_BUFFER_UNLOCK_CORE(CORE1, coreID);
}
return KAL_TRUE;
}
// NOTE : if this gid needs to merge to a file, call mcf_merge_ota_buffer to combine this buffer
kal_bool mcf_merge_one_gid(void *new_gid, mcf_ota_type_enum type, void *output_buffer, kal_uint32 output_buffer_size, kal_uint32 operation_mask)
{
MD_TRC_MCF_TR_MERGE_ONE_GID_START();
if (new_gid == NULL || output_buffer == NULL) {
MD_TRC_MCF_TR_MERGE_ONE_GID_INPUT_PARAM_ERROR((kal_uint32)new_gid, (kal_uint32)output_buffer);
return KAL_FALSE;
}
mcf_tool_file_info_t copy_header;
mcf_tool_file_info_t *output_header = (mcf_tool_file_info_t *)output_buffer;
kal_uint32 gid_size = 0;
copy_header.file_version = 3;
copy_header.operation_mask = operation_mask;
mcf_merge_make_ota_file_header(output_header, &copy_header); // copy first header to output header
if (type == MCF_TYPE_OTA)
{
strcpy(output_header->file_type, MCF_FILE_TYPE_OTA);
mcf_tool_gid_ota_file_item_t *ota = new_gid;
gid_size = ota->total_len;
MD_TRC_MCF_TR_MERGE_OTA_BUFFER_OUTPUT_GID(ota->global_id);
mcf_dump_data(KAL_FALSE, &ota->buff_start + ota->array_index_len, ota->value_len);
}
else if (type == MCF_TYPE_OTA_BY_OP)
{
strcpy(output_header->file_type, MCF_FILE_TYPE_TLVOTA);
mcf_tool_gid_tlvota_file_item_t *ota_by_op = new_gid;
gid_size = ota_by_op->total_len;
MD_TRC_MCF_TR_MERGE_OTA_BUFFER_OUTPUT_GID(ota_by_op->global_id);
mcf_dump_data(KAL_FALSE, &ota_by_op->buff_start + ota_by_op->tag_len + ota_by_op->array_index_len, ota_by_op->value_len);
}
else
{
return KAL_FALSE;
}
// check buffer size
if ((output_header->total_len + gid_size) > output_buffer_size) {
MD_TRC_MCF_TR_MERGE_OTA_BUFFER_OUTPUT_BUFFER_OUT_OF_SIZE((output_header->total_len + gid_size), output_buffer_size);
return KAL_FALSE;
}
kal_mem_cpy((kal_uint8 *)output_buffer + output_header->total_len, new_gid, gid_size);
output_header->item_num = 1;
output_header->file_size = (kal_uint32)((kal_uint8 *)output_buffer + output_header->total_len + gid_size - (kal_uint8 *)output_header);
if (((output_header->file_size - output_header->total_len) % 4) != 0)
output_header->file_size += 4 - (output_header->file_size - output_header->total_len) % 4; // content should be 16 bytes alignment
// ========== security ==========
{
mcf_tool_file_info_t *file_header = (mcf_tool_file_info_t *)output_buffer;
// checksum
if (file_header->operation_mask & MCF_FILE_OP_CHECKSUM)
{
file_header->checksum = 0;
file_header->checksum = mcf_calc_check_sum((kal_uint32 *)output_buffer, file_header->file_size);
}
// encrypt
if (file_header->operation_mask & MCF_FILE_OP_AES_128 || file_header->operation_mask & MCF_FILE_OP_AES_256)
{
// this output is temp buffer, no need to encrypt
file_header->operation_mask &= ~(MCF_FILE_OP_AES_128);
file_header->operation_mask &= ~(MCF_FILE_OP_AES_256);
}
}
MD_TRC_MCF_TR_MERG_ONE_GID_END();
return KAL_TRUE;
}
#endif
// password will be auto padding to 32B
// content should be padding to 32B alignment
// conrent length should be mod by 32
kal_bool mcf_encrypt_256bit(char *password, char *content, kal_uint32 content_length)
{
kal_uint8 iv[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f};
kal_uint8 copy_len = 0;
kal_uint32 output_len;
t_cust_chl_sym_key key;
AES_PARAM aes_param;
kal_uint32 ret = CUST_CHL_ERROR_NONE;
kal_uint32 start_time = ust_get_current_time();
kal_mem_set(&aes_param, 0, sizeof(AES_PARAM));
if (content == NULL) return KAL_FALSE;
if (content_length % 16 != 0) return KAL_FALSE;
copy_len = strlen(password);
if (copy_len > 32) copy_len = 32;
key.m_key_len = 32;
kal_mem_set(key.m_key, 0, sizeof(key.m_key));
kal_mem_cpy(&key.m_key, password, copy_len);
aes_param.IVLength = 16;
aes_param.IV = iv;
ret = CustCHL_AES_Encrypt_data(CUST_CHL_ALG_AES256, CUST_CHL_MODE_CBC, content_length, (kal_uint8 *)content, &output_len, (kal_uint8 *)content, &key, &aes_param);
MD_TRC_MCF_TR_ENCRYPT(ust_us_duration(start_time, ust_get_current_time()));
if (ret != CUST_CHL_ERROR_NONE)
return KAL_FALSE;
return KAL_TRUE;
}
// password will be auto padding to 32B
// content should be padding to 32B alignment
// conrent length should be mod by 32
kal_bool mcf_decrypt_256bit(char *password, char *content, kal_uint32 content_length)
{
kal_uint8 iv[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f};
kal_uint8 copy_len = 0;
kal_uint32 output_len;
t_cust_chl_sym_key key;
AES_PARAM aes_param;
kal_uint32 ret = CUST_CHL_ERROR_NONE;
kal_uint32 start_time = ust_get_current_time();
kal_mem_set(&aes_param, 0, sizeof(AES_PARAM));
if (content == NULL) return KAL_FALSE;
if (content_length % 16 != 0) return KAL_FALSE;
copy_len = strlen(password);
if (copy_len > 32) copy_len = 32;
key.m_key_len = 32;
kal_mem_set(key.m_key, 0, sizeof(key.m_key));
kal_mem_cpy(&key.m_key, password, copy_len);
aes_param.IVLength = 16;
aes_param.IV = iv;
ret = CustCHL_AES_Decrypt_data(CUST_CHL_ALG_AES256, CUST_CHL_MODE_CBC, content_length, (kal_uint8 *)content, &output_len, (kal_uint8 *)content, &key, &aes_param);
MD_TRC_MCF_TR_DECRYPT(ust_us_duration(start_time, ust_get_current_time()));
if (ret != CUST_CHL_ERROR_NONE)
return KAL_FALSE;
return KAL_TRUE;
}
// digest verify
kal_bool mcf_verify_digest(kal_uint32 digest_tag, mcf_tool_file_info_t *ota_file, mcf_digest *sign)
{
kal_uint32 ret = KAL_FALSE;
t_cust_chl_asym_key key;
if (digest_tag == MCF_FILE_OP_SHA256_RSA2048) {
ret = mcf_get_custom_digest_public_key(sign->sequence, &key);
if (ret == KAL_FALSE) return KAL_FALSE;
ret = CustCHL_Verify_RSA_Signature(CUST_CHL_ALG_RSA_PKCS1_V15_SHA256_ASN1, (kal_uint8 *)ota_file, ota_file->file_size, sign->digest_value, sign->digest_len, &key);
}
else if(digest_tag == MCF_FILE_OP_SHA384_RSA3072){
ret = mcf_get_custom_digest_public_key(sign->sequence, &key);
if (ret == KAL_FALSE) return KAL_FALSE;
ret = CustCHL_Verify_RSA_Signature(CUST_CHL_ALG_RSA_PKCS1_V15_SHA384_ASN1, (kal_uint8 *)ota_file, ota_file->file_size, sign->digest_value, sign->digest_len, &key);
}
else
{
// not support
return KAL_FALSE;
}
if (ret != CUST_CHL_ERROR_NONE)
return KAL_FALSE;
return KAL_TRUE;
}
void mcf_make_file_info(mcf_file_info_t *file_info, kal_uint8 path_type, kal_char *name, kal_char *sw_version, kal_uint8 sw_version_len, kal_char *gen_time, kal_uint8 gen_time_len, kal_uint64 last_mod_time, kal_uint32 checksum)
{
MD_TRC_MCF_TR_MAKE_FILE_INFO_START(path_type, last_mod_time & 0xFFFFFFFF, checksum & 0xFFFFFFFF);
kal_mem_set(file_info, 0, sizeof(mcf_file_info_t));
file_info->path_type = path_type;
strncpy(file_info->name, name, MCF_FILE_MAX_NAME_LEN-1);
strncpy(file_info->sw_version, sw_version, sw_version_len);
strncpy(file_info->gen_time, gen_time, gen_time_len);
file_info->last_mod_time = last_mod_time;
file_info->checksum = checksum;
file_info->sw_version_len = sw_version_len;
file_info->gen_time_len = gen_time_len;
}
kal_bool mcf_compare_file_info(mcf_file_info_t *old_file, mcf_file_info_t *new_file)
{
static nvram_ef_mcf_sw_info_struct nv_sw_info;
MD_TRC_MCF_TR_COMPARE_FILE_INFO_START();
MD_TRC_MCF_TR_COMPARE_FILE_INFO_OLD_FILE_INFO(old_file->sw_version, old_file->gen_time);
MD_TRC_MCF_TR_COMPARE_FILE_INFO_NEW_FILE_INFO(new_file->sw_version, new_file->gen_time);
MD_TRC_MCF_TR_COMPARE_FILE_INFO_FILE_CHECKSUM(old_file->checksum & 0xFFFFFFFF, new_file->checksum & 0xFFFFFFFF);
MD_TRC_MCF_TR_COMPARE_FILE_INFO_FILE_LAST_MOD_TIME(old_file->last_mod_time & 0xFFFFFFFF, new_file->last_mod_time & 0xFFFFFFFF);
if ( (strncmp(old_file->sw_version, new_file->sw_version, new_file->sw_version_len) == 0) &&
(strncmp(old_file->gen_time, new_file->gen_time, new_file->gen_time_len) == 0) &&
(old_file->path_type == new_file->path_type) &&
(strncmp(old_file->name, new_file->name, MCF_FILE_MAX_NAME_LEN) == 0) &&
(old_file->last_mod_time == new_file->last_mod_time) &&
(old_file->checksum == new_file->checksum) ) {
if ( !nvram_external_read_data(NVRAM_EF_MCF_SW_INFO_LID, 1, (kal_uint8 *)&nv_sw_info, sizeof(nvram_ef_mcf_sw_info_struct))) {
MD_TRC_MCF_TR_COMPARE_FILE_INFO_READ_FILE_NVRAM_FAIL(NVRAM_EF_MCF_SW_INFO_LID);
return KAL_FALSE;
}
if ((strncmp(nv_sw_info.version, release_verno(), MCF_SW_VERNO_LEN) == 0) &&
(strncmp(nv_sw_info.build_time, build_date_time(), MCF_SW_BUILD_TIME_LEN) == 0)){
MD_TRC_MCF_TR_COMPARE_FILE_INFO_MD_INFO(nv_sw_info.version, nv_sw_info.build_time);
return KAL_TRUE;
}else{
MD_TRC_MCF_TR_COMPARE_FILE_INFO_FILE_NOT_THE_SAME();
return KAL_FALSE;
}
}else{
MD_TRC_MCF_TR_COMPARE_FILE_INFO_FILE_NOT_THE_SAME();
return KAL_FALSE;
}
}