blob: b045b0d349571a7227ff47d6f2309c4c17d65f7b [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) 2005
*
* 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:
* ---------
* nvram_drval_fat.c
*
* Project:
* --------
* MAUI
*
* Description:
* ------------
* This is Driver adaption level functions.
*
* 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!
*
* 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!
* 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!
* 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
*****************************************************************************/
#include "stdio.h"
#include "string.h"
#include "stdarg.h"
#include "kal_general_types.h"
#include "kal_public_api.h"
#include "fs_type.h"
#include "fs_func.h"
#include "fs_errcode.h"
#include "nvram_main.h"
#if defined(__NVRAM_ACCESS_TIMEOUT_ASSERT__)
#include "dcl_gpt.h"
#endif
#ifdef __NVRAM_LID_CACHE__
#include "nvram_cache_interface.h"
#endif
#if defined(__MTK_TARGET__)
#include "SST_secure.h"
#endif
#include "us_timer.h"
#include "ex_public.h"
/*****************************************************************************
* Define
*****************************************************************************/
/*****************************************************************************
* Global Variable
*****************************************************************************/
extern kal_mutexid g_nvram_fs_mutex;
#if defined(__NVRAM_ACCESS_TIMEOUT_ASSERT__)
extern DCL_HANDLE nvram_gpt_handle;
#endif
#ifdef __NVRAM_WRITE_WITH_FILE_SIZE__
extern kal_bool bResetNvramData;
#endif
#ifdef __NVRAM_CHECK_FILE_AND_RECOVER__
extern kal_bool Cali_filelist_found;
extern kal_bool Imei_filelist_found;
extern kal_bool is_nvram_in_ota_flow;
extern kal_bool is_nvram_first_restore;
extern kal_uint8 *CALI_FileListBuf;
extern kal_uint8 *IMEI_FileListBuf;
#endif
extern nvram_ee_info_type* nvram_ee_info;
extern kal_char nvram_trace_dump_temp_buffer[];
extern kal_char nvram_trace_dump_buffer[];
extern kal_mutexid g_nvram_dump_trace_mutex;
extern kal_wchar nvram_trace_filename[];
extern FS_HANDLE nvram_trace_file_hdl;
extern kal_uint32 nvram_trace_dump_buffer_offset;
extern module_type stack_get_active_module_id( void );
/*****************************************************************************
* Local Variable
*****************************************************************************/
static kal_int32 nvram_fat_last_err;
static kal_uint32 nvram_fat_last_line;
static kal_uint8 g_chksum[128] = {0};
#ifdef __NVRAM_CRYPT_TEST__
extern kal_uint32 bWriteMsp;
extern kal_uint32 bReadMsp;
#define NVRAM_SWCHANGE_REPORT_MSP_ENCRYPT_FILE "Z:\\NVRAM\\W_TST"
#define NVRAM_SWCHANGE_REPORT_MSP_DENCRYPT_FILE "Z:\\NVRAM\\R_TST"
static kal_uint8 NVRAM_EF_MSP_TEST_W[NVRAM_MSP_TEST_LEN * 3];
static kal_uint8 NVRAM_EF_MSP_TEST_R[NVRAM_MSP_TEST_LEN * 3];
#endif
#ifndef __MTK_TARGET__ /* Simulate by nvram on MODIS */
void SST_Secure_Algo (kal_uint8 Direction, kal_uint32 ContentAddr,
kal_uint32 ContentLen, kal_uint8 *CustomSeed,
kal_uint8 *ResText)
{
/*----------------------------------------------------------------*/
/* Local Variables */
/*----------------------------------------------------------------*/
kal_uint8 *source = (kal_uint8 *) ContentAddr;
kal_int32 i;
/*----------------------------------------------------------------*/
/* Code Body */
/*----------------------------------------------------------------*/
if ((ContentAddr & 0x03) != 0)
{
NVRAM_EXT_ASSERT(KAL_FALSE, ContentAddr, NVRAM_LOC_ADDRESS_ALIGN_FAIL_1, 0);
}
if (NVRAM_MSP_ALIGNMENT_REMAINDER(ContentLen) != 0)
{
NVRAM_EXT_ASSERT(KAL_FALSE,ContentLen , NVRAM_LOC_LENGTH_ALIGN_FAIL_1, 0);
}
for (i = 0 ;i < ContentLen; i ++)
{
*(ResText+i) = *(source+i) ^ i;
}
}
#endif
/*****************************************************************************
* FUNCTION
* nvram_gpt_timeout_callback
* DESCRIPTION
* if FS access timeout will trigger assert
* PARAMETERS
* RETURNS
*****************************************************************************/
#if defined(__NVRAM_ACCESS_TIMEOUT_ASSERT__)
void nvram_gpt_timeout_callback(void *data)
{
//timeout assert
NVRAM_EXT_ASSERT(KAL_FALSE,0, NVRAM_LOC_ACCESS_TIMEOUT_1, 0);
}
#endif
/*****************************************************************************
* FUNCTION
* nvram_fat_last_err
* DESCRIPTION
* get the last error in nvram drv fat
* PARAMETERS
* RETURNS
*****************************************************************************/
kal_int32 nvram_drv_fat_get_last_err(void)
{
/*----------------------------------------------------------------*/
/* Local Variables */
/*----------------------------------------------------------------*/
/*----------------------------------------------------------------*/
/* Code Body */
/*----------------------------------------------------------------*/
return nvram_fat_last_err;
}
/*****************************************************************************
* FUNCTION
* nvram_fat_last_line
* DESCRIPTION
* get the last error in nvram drv fat
* PARAMETERS
* RETURNS
*****************************************************************************/
kal_uint32 nvram_drv_fat_get_last_line(void)
{
/*----------------------------------------------------------------*/
/* Local Variables */
/*----------------------------------------------------------------*/
/*----------------------------------------------------------------*/
/* Code Body */
/*----------------------------------------------------------------*/
return nvram_fat_last_line;
}
#ifdef __NVRAM_CRYPT_TEST__
static kal_bool nvram_create_report_msp_file(kal_bool bWrite)
{
/*----------------------------------------------------------------*/
/* Local Variables */
/*----------------------------------------------------------------*/
kal_wchar filename[NVRAM_MAX_PATH_LEN];
FS_HANDLE handle;
kal_uint32 filelen = NVRAM_MSP_TEST_LEN*3;
kal_uint32 written;
kal_int32 result = FS_NO_ERROR;
/*----------------------------------------------------------------*/
/* Code Body */
/*----------------------------------------------------------------*/
if ( bWrite )
{
kal_wsprintf(filename, "%s", NVRAM_SWCHANGE_REPORT_MSP_ENCRYPT_FILE);
NVRAM_FS_START_EX(FS_OP_GETATTRIBUTES,filename);
result = FS_GetAttributes(filename);
NVRAM_FS_END(FS_OP_GETATTRIBUTES,result);
if (result >= FS_NO_ERROR)
{
NVRAM_FS_START_EX(FS_OP_DELETE, filename);
result = FS_Delete(filename);
NVRAM_FS_END(FS_OP_DELETE,result);
}
NVRAM_FS_START_EX(FS_OP_OPEN,filename);
handle = FS_Open(filename, FS_CREATE_ALWAYS | FS_READ_WRITE);
NVRAM_FS_END(FS_OP_OPEN,handle);
if (handle > FS_NO_ERROR)
{
NVRAM_FS_START(FS_OP_WRITE);
result = FS_Write(handle, &NVRAM_EF_MSP_TEST_W, filelen, &written);
NVRAM_FS_END(FS_OP_WRITE,result);
if (result != FS_NO_ERROR)
{
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]%s->FS_Write fail at %d,result=%d \r\n",__FUNCTION__,__LINE__,result);
NVRAM_FS_START(FS_OP_CLOSE);
result = FS_Close(handle);
NVRAM_FS_END(FS_OP_CLOSE,result);
bWriteMsp = 0;
return KAL_FALSE;
}
}
else
{
return KAL_FALSE;
}
NVRAM_FS_START(FS_OP_CLOSE);
result = FS_Close(handle);
NVRAM_FS_END(FS_OP_CLOSE,result);
bWriteMsp = 0;
}
else
{
kal_wsprintf(filename, "%s", NVRAM_SWCHANGE_REPORT_MSP_DENCRYPT_FILE);
NVRAM_FS_START_EX(FS_OP_GETATTRIBUTES,filename);
result = FS_GetAttributes(filename);
NVRAM_FS_END(FS_OP_GETATTRIBUTES,result);
if (result >= FS_NO_ERROR)
{
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]%s->FS_GetAttributes fail at %d,result=%d \r\n",__FUNCTION__,__LINE__,result);
NVRAM_FS_START_EX(FS_OP_DELETE,filename);
result = FS_Delete(filename);
NVRAM_FS_END(FS_OP_DELETE,result);
}
NVRAM_FS_START_EX(FS_OP_OPEN,filename);
handle = FS_Open(filename, FS_CREATE_ALWAYS | FS_READ_WRITE);
NVRAM_FS_END(FS_OP_OPEN,handle);
if (handle > FS_NO_ERROR)
{
NVRAM_FS_START(FS_OP_WRITE);
result = FS_Write(handle, &NVRAM_EF_MSP_TEST_R, filelen, &written);
NVRAM_FS_END(FS_OP_WRITE,result);
if (result != FS_NO_ERROR)
{
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]%s->FS_Write fail at %d,result=%d \r\n",__FUNCTION__,__LINE__,result);
NVRAM_FS_START(FS_OP_CLOSE);
result = FS_Close(handle);
NVRAM_FS_END(FS_OP_CLOSE,result);
bReadMsp = 0;
return KAL_FALSE;
}
}
else
{
return KAL_FALSE;
}
NVRAM_FS_START(FS_OP_CLOSE);
result = FS_Close(handle);
NVRAM_FS_END(FS_OP_CLOSE,result);
bReadMsp = 0;
}
return KAL_TRUE;
}
#endif
/*****************************************************************************
* FUNCTION
* nvram_drv_fat_init
* DESCRIPTION
* This is nvram_drv_fat_init() function of NVRAM module.
* PARAMETERS
* void
* RETURNS
* if NVRAM folder does not exist, it means the FAT is empty.
*****************************************************************************/
nvram_drv_status_enum nvram_drv_fat_status(void)
{
/*----------------------------------------------------------------*/
/* Local Variables */
/*----------------------------------------------------------------*/
kal_wchar filename[NVRAM_MAX_PATH_LEN];
FS_HANDLE hFile;
nvram_folder_enum i;
kal_int32 result = FS_NO_ERROR;
/*----------------------------------------------------------------*/
/* Code Body */
/*----------------------------------------------------------------*/
if(nvram_ee_info != NULL){
nvram_ee_info->nvram_init_step = NVRAM_CORE_INIT_FIRST_BOOT_START;
nvram_ee_info->nvram_init_type = NVRAM_INIT_NORMAL_BOOT_UP;
}
#if !(defined(_SIMULATION) || defined(__PALLADIUM__) || defined(__FPGA__))
if (nvram_check_first_bootup_log("FAT"))
{
if(nvram_ee_info != NULL){
nvram_ee_info->nvram_init_step = NVRAM_CORE_INIT_FIRST_BOOT_CHECK_DONE;
nvram_ee_info->nvram_init_type = NVRAM_INIT_FIRST_BOOT_UP;
}
return NVRAM_DRV_UNFORMATTED;
}
#endif
NVRAM_FS_MAKE_ROOT_PATH(filename);
NVRAM_FS_START_EX(FS_OP_OPEN,filename);
hFile = FS_Open((const kal_wchar*)filename, FS_READ_ONLY | FS_OPEN_DIR);
NVRAM_FS_END(FS_OP_OPEN,hFile);
if (hFile == FS_FILE_NOT_FOUND || hFile == FS_PATH_NOT_FOUND)
{
if(nvram_ee_info != NULL){
nvram_ee_info->nvram_init_step = NVRAM_CORE_INIT_FIRST_BOOT_CHECK_DONE;
nvram_ee_info->nvram_init_type = NVRAM_INIT_FIRST_BOOT_UP;
}
return NVRAM_DRV_UNFORMATTED;
}
else if (hFile == FS_FDM_USER_DRIVE_BROKEN ||
hFile == FS_FDM_SYS_DRIVE_BROKEN ||
hFile == FS_FDM_MULTIPLE_BROKEN)
{
if(nvram_ee_info != NULL){
nvram_ee_info->nvram_init_step = NVRAM_CORE_INIT_FIRST_BOOT_CHECK_DONE;
nvram_ee_info->nvram_init_context.dev_broken = KAL_TRUE;
}
return NVRAM_DRV_DRIVE_BROKEN;
}
else if (hFile == FS_FDM_VERSION_MISMATCH)
{
if(nvram_ee_info != NULL){
nvram_ee_info->nvram_init_step = NVRAM_CORE_INIT_FIRST_BOOT_CHECK_DONE;
nvram_ee_info->nvram_init_context.dev_broken = KAL_TRUE;
}
return NVRAM_DRV_DRIVE_VNOERR;
}
else if (hFile >= FS_NO_ERROR) /* Success */
{
NVRAM_FS_START(FS_OP_CLOSE);
result = FS_Close(hFile);
NVRAM_FS_END(FS_OP_CLOSE,result);
}
else
{
MD_TRC_FUNC_NVRAM_DRV_FAT_THROW_EXCEPTION(hFile, __LINE__);
NVRAM_EXT_ASSERT(KAL_FALSE, (kal_uint32) hFile, NVRAM_LOC_OPEN_NV_FOLDER_FAIL_3, 0);
if(nvram_ee_info != NULL){
nvram_ee_info->nvram_init_step = NVRAM_CORE_INIT_FIRST_BOOT_CHECK_DONE;
}
return NVRAM_DRV_FATAL_ERROR;
}
for (i = NVRAM_FOLDER_BEGIN; i < NVRAM_FOLDER_TOTAL; i++)
{
kal_wsprintf(filename, "%s", nvram_query_work_path(i));
NVRAM_FS_START_EX(FS_OP_GETATTRIBUTES, filename);
result = FS_GetAttributes(filename);
NVRAM_FS_END(FS_OP_GETATTRIBUTES,result);
if (FS_NO_ERROR > result)
{
if(nvram_ee_info != NULL){
nvram_ee_info->nvram_init_step = NVRAM_CORE_INIT_FACTORY_BOOT_START;
}
return NVRAM_DRV_FOLDER_NOT_READY;
}
}
return NVRAM_DRV_OK;
}
/*****************************************************************************
* FUNCTION
* nvram_drv_fat_init
* DESCRIPTION
* This is nvram_drv_fat_init() function of NVRAM module.
* PARAMETERS
* void
* RETURNS
* if NVRAM folder does not exist, it means the FAT is empty.
*****************************************************************************/
nvram_drv_status_enum nvram_drv_fat_init_start(void)
{
/*----------------------------------------------------------------*/
/* Local Variables */
/*----------------------------------------------------------------*/
kal_wchar filename[NVRAM_MAX_PATH_LEN];
kal_int32 Ret = FS_NO_ERROR;
/*----------------------------------------------------------------*/
/* Code Body */
/*----------------------------------------------------------------*/
Ret = NVRAM_FS_GET_FULL_PATH_LEN;
nvram_create_first_bootup_log("FAT");
if(nvram_ee_info != NULL){
nvram_ee_info->nvram_init_step = NVRAM_CORE_INIT_FIRST_BOOT_CREATE_FAT_FILE_DONE;
}
/* check nvram root folder, if not exist, create it! */
NVRAM_FS_MAKE_ROOT_PATH(filename);
NVRAM_FS_START_EX(FS_OP_GETATTRIBUTES, filename);
Ret = FS_GetAttributes(filename);
NVRAM_FS_END(FS_OP_GETATTRIBUTES,Ret);
if(FS_NO_ERROR > Ret)
{
NVRAM_FS_START_EX(FS_OP_CREATEDIR,filename);
Ret = FS_CreateDir((const kal_wchar*)filename);
NVRAM_FS_END(FS_OP_CREATEDIR,Ret);
MD_TRC_FUNC_NVRAM_DRV_FAT_THROW_EXCEPTION(Ret, __LINE__);
}
if(nvram_ee_info != NULL){
nvram_ee_info->nvram_init_step = NVRAM_CORE_INIT_FIRST_BOOT_CREATE_MAIN_FOLDER_DONE;
}
nvram_create_all_folder();
if(nvram_ee_info != NULL){
nvram_ee_info->nvram_init_step = NVRAM_CORE_INIT_FIRST_BOOT_CREATE_ALL_FOLDER_DONE;
nvram_ee_info->nvram_init_time[2] = kal_get_systicks();
}
return NVRAM_DRV_OK;
}
/*****************************************************************************
* FUNCTION
* nvram_drv_fat_init
* DESCRIPTION
* This is nvram_drv_fat_init() function of NVRAM module.
* PARAMETERS
* void
* RETURNS
* if NVRAM folder does not exist, it means the FAT is empty.
*****************************************************************************/
nvram_drv_status_enum nvram_drv_fat_init_end(void)
{
/*----------------------------------------------------------------*/
/* Local Variables */
/*----------------------------------------------------------------*/
/*----------------------------------------------------------------*/
/* Code Body */
/*----------------------------------------------------------------*/
nvram_delete_first_bootup_log("FAT");
if(nvram_ee_info != NULL){
nvram_ee_info->nvram_init_step = NVRAM_CORE_INIT_FIRST_BOOT_DELETE_FAT_FILE_DONE;
}
return NVRAM_DRV_OK;
}
/*****************************************************************************
* FUNCTION
* nvram_drv_fat_format
* DESCRIPTION
* Dummy format function.
* PARAMETERS
* void
* RETURNS
* void
*****************************************************************************/
void nvram_drv_fat_format(void)
{
/*----------------------------------------------------------------*/
/* Local Variables */
/*----------------------------------------------------------------*/
/*----------------------------------------------------------------*/
/* Code Body */
/*----------------------------------------------------------------*/
/* Folder is ready as init, nothing to do in format */
return;
}
/*****************************************************************************
* FUNCTION
* nvram_drv_fat_nvram_drv_fat_backup
* DESCRIPTION
* To make a backup.
* PARAMETERS
* prefix [IN] file prefix
* verno [IN] file verno
* a_to_b [IN] direction
* RETURNS
* error code
*****************************************************************************/
kal_int32 nvram_drv_fat_backup(nvram_ltable_entry_struct *ldi, kal_bool a_to_b)
{
/*----------------------------------------------------------------*/
/* Local Variables */
/*----------------------------------------------------------------*/
kal_wchar src_path[NVRAM_MAX_PATH_LEN], dest_path[NVRAM_MAX_PATH_LEN];
NVRAM_FILE_NAME nvramname;
kal_int32 result = FS_NO_ERROR;
/*----------------------------------------------------------------*/
/* Code Body */
/*----------------------------------------------------------------*/
if (a_to_b)
{
nvram_util_make_lid_filename(ldi, nvramname, KAL_TRUE); // A
nvram_query_file_name(nvram_query_folder_index_ex(ldi->category, KAL_TRUE), nvramname, src_path);
#ifdef __NVRAM_BACKUP_DISK_FAT__
if (NVRAM_IS_ATTR_BACKUP_FAT(ldi->attr))
{
nvram_util_make_lid_filename(ldi, nvramname, KAL_TRUE);
nvram_query_file_name(NVRAM_NVD_BAK, nvramname, dest_path);
}
else
#endif
{
nvram_util_make_lid_filename(ldi, nvramname, KAL_FALSE); // B
nvram_query_file_name(nvram_query_folder_index_ex(ldi->category, KAL_FALSE), nvramname, dest_path);
}
}
else
{
#ifdef __NVRAM_BACKUP_DISK_FAT__
if (NVRAM_IS_ATTR_BACKUP_FAT(ldi->attr))
{
nvram_util_make_lid_filename(ldi, nvramname, KAL_TRUE);
nvram_query_file_name(NVRAM_NVD_BAK, nvramname, src_path);
}
else
#endif
{
nvram_util_make_lid_filename(ldi, nvramname, KAL_FALSE); // B
nvram_query_file_name(nvram_query_folder_index_ex(ldi->category, KAL_FALSE), nvramname, src_path);
}
nvram_util_make_lid_filename(ldi, nvramname, KAL_TRUE); // A
nvram_query_file_name(nvram_query_folder_index_ex(ldi->category, KAL_TRUE), nvramname, dest_path);
}
#ifndef __LOW_COST_SUPPORT_ULC__
// FS_SetAttributes(dest_path, 0);
NVRAM_FS_START_EX(FS_OP_DELETE,dest_path);
result = FS_Delete(dest_path);
NVRAM_FS_END(FS_OP_DELETE,result);
NVRAM_FS_START_EX(FS_OP_MOVE,src_path);
result = FS_Move(src_path, dest_path, FS_MOVE_COPY, NULL, NULL, 0);
NVRAM_FS_END(FS_OP_MOVE,result);
#else
{
FS_HANDLE src, dest;
NVRAM_FS_START_EX(FS_OP_OPEN,src_path);
src = FS_Open(src_path, FS_READ_ONLY);
NVRAM_FS_END(FS_OP_OPEN,src);
NVRAM_FS_START_EX(FS_OP_OPEN,dest_path);
dest = FS_Open(dest_path, FS_READ_WRITE | FS_CREATE_ALWAYS);
NVRAM_FS_END(FS_OP_OPEN,dest);
if (src >= FS_NO_ERROR && dest >= FS_NO_ERROR)
{
kal_uint32 len;
kal_uint8 *buf = (kal_uint8 *)get_ctrl_buffer(MAX_NVRAM_RECORD_SIZE);
NVRAM_FS_START(FS_OP_READ);
result = FS_Read(src, buf, MAX_NVRAM_RECORD_SIZE, &len);
NVRAM_FS_END(FS_OP_READ,result);
while ((ret == FS_NO_ERROR) &&
result >= FS_NO_ERROR &&
(len > 0))
{
NVRAM_FS_START(FS_OP_WRITE);
result = FS_Write(dest, buf, len, &len);
NVRAM_FS_END(FS_OP_WRITE,result);
}
nvram_fat_last_err = ret;
nvram_fat_last_line = __LINE__;
NVRAM_FS_START(FS_OP_CLOSE);
result = FS_Close(src);
NVRAM_FS_END(FS_OP_CLOSE,result);
NVRAM_FS_START(FS_OP_CLOSE);
result = FS_Close(dest);
NVRAM_FS_END(FS_OP_CLOSE,result);
free_ctrl_buffer(buf);
buf = NULL;
}
else
{
if (src < FS_NO_ERROR)
return src;
else
return dest;
}
}
#endif
#ifdef __NVRAM_LID_CACHE__
if(result >= FS_NO_ERROR)
{
if((!NVRAM_IS_ATTR_RAW_DATA(ldi->attr)) && NVRAM_RD_WITH_CACHE(ldi->LID))
{
unmask_valid_bit_by_ltable_entry(ldi, 0, (ldi->total_records + 1));
}
}
#endif
return result;
}
#if defined(__NVRAM_FS_OPERATION_COMPACT__) && defined(__NVRAM_FS_CMPT_SIMULATION__)
/*****************************************************************************
* FUNCTION
* FS_CMPT_Read
* DESCRIPTION
* To simulate SP FS CMPT API
* RETURNS
* error code
*****************************************************************************/
kal_int32 FS_CMPT_Read(const WCHAR * FileName, NVRAM_FS_PARAM_CMPT_T* nvram_param)
{
FS_HANDLE hFile;
int result;
kal_int32 ret = FS_NO_ERROR;
if((nvram_param->opid_map & (NVRAM_FS_CMPT_OPEN)) == (NVRAM_FS_CMPT_OPEN)){
nvram_param->ret[0] |= NVRAM_FS_CMPT_OPEN;
NVRAM_FS_START_EX(FS_OP_OPEN,FileName);
hFile = FS_Open((const kal_wchar*)FileName, nvram_param->Flag);
NVRAM_FS_END(FS_OP_OPEN,hFile);
if (hFile < FS_NO_ERROR)
{
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]%s ->FS_Open fail at %d,hFile=%d \r\n",__FUNCTION__,__LINE__,hFile);
nvram_param->ret[1] = hFile;
return hFile;
}
}
if((nvram_param->opid_map & (NVRAM_FS_CMPT_GETFILESIZE)) == (NVRAM_FS_CMPT_GETFILESIZE)){
nvram_param->ret[0] |= NVRAM_FS_CMPT_GETFILESIZE;
NVRAM_FS_START(FS_OP_GETFILESIZE);
result = FS_GetFileSize(hFile, nvram_param->FileSize);
NVRAM_FS_END(FS_OP_GETFILESIZE,result);
if (result < FS_NO_ERROR)
{
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]%s ->FS_GetFileSize fail at %d,result=%d \r\n",__FUNCTION__,__LINE__,result);
nvram_param->ret[1] = result;
NVRAM_FS_START(FS_OP_CLOSE);
ret = FS_Close(hFile);
NVRAM_FS_END(FS_OP_CLOSE,ret);
return result;
}
}
if((nvram_param->opid_map & (NVRAM_FS_CMPT_SEEK)) == (NVRAM_FS_CMPT_SEEK)){
nvram_param->ret[0] |= NVRAM_FS_CMPT_SEEK;
NVRAM_FS_START(FS_OP_SEEK);
result = FS_Seek(hFile, nvram_param->Offset, nvram_param->Whence);
NVRAM_FS_END(FS_OP_SEEK,result);
if (result < FS_NO_ERROR)
{
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]%s ->FS_Seek fail at %d,result=%d \r\n",__FUNCTION__,__LINE__,result);
nvram_param->ret[1] = result;
NVRAM_FS_START(FS_OP_CLOSE);
ret = FS_Close(hFile);
NVRAM_FS_END(FS_OP_CLOSE,ret);
return result;
}
}
if((nvram_param->opid_map & (NVRAM_FS_CMPT_READ)) == (NVRAM_FS_CMPT_READ)){
nvram_param->ret[0] |= NVRAM_FS_CMPT_READ;
NVRAM_FS_START(FS_OP_READ);
result = FS_Read(hFile, nvram_param->DataPtr, nvram_param->Length, nvram_param->Read);
NVRAM_FS_END(FS_OP_READ,result);
if (result < FS_NO_ERROR)
{
nvram_param->ret[1] = result;
NVRAM_FS_START(FS_OP_CLOSE);
ret = FS_Close(hFile);
NVRAM_FS_END(FS_OP_CLOSE,ret);
return result;
}
}
nvram_param->ret[0] |= NVRAM_FS_CMPT_CLOSE;
NVRAM_FS_START(FS_OP_CLOSE);
result = FS_Close(hFile);
NVRAM_FS_END(FS_OP_CLOSE,result);
return result;
}
#endif /* __NVRAM_FS_CMPT_SIMULATION__ */
#if (defined(__NVRAM_FS_OPERATION_COMPACT__)&& defined(__CCCIFS_SUPPORT__) && defined(__MTK_TARGET__)) || defined(__NVRAM_FS_CMPT_SIMULATION__)
/*****************************************************************************
* FUNCTION
* nvram_drv_fat_read_section_cmpt
* DESCRIPTION
* read record(s) from FAT.
* PARAMETERS
* hFile [IN] file handle
* rec_index [IN] which record to read (start)
* rec_amount [IN] how many record to read at once
* rec_size [IN] size of record
* buffer [IN/OUT] buffer of check sum
* type [IN] read content or checksum
* ismsp [IN] to indicate that the records protected by hw
* RETURNS
* = 0: success
* > 0: NVRAM error code
* < 0: FS error code
*****************************************************************************/
kal_int32 nvram_drv_fat_read_section_cmpt(
FS_HANDLE hFile,
kal_uint16 rec_index,
kal_uint16 rec_amount,
kal_uint32 rec_size,
kal_uint8 *buffer,
nvram_drv_read_type_enum type,
nvram_ltable_entry_struct *ldi,
kal_wchar *filename,
NVRAM_FS_PARAM_CMPT_T *nvram_param
)
{
/*----------------------------------------------------------------*/
/* Local Variables */
/*----------------------------------------------------------------*/
kal_uint16 chksum3 = 0;
kal_uint8 *chksum1 = NULL;
kal_uint8 *chksum2 = NULL;
kal_uint32 len = 0, remainLen = 0;
kal_uint32 section_size;
kal_uint32 working_buffer_size;
kal_uint8 *working_buffer = NULL;
kal_int32 result = NVRAM_DRV_OK;
kal_uint32 i,j;
kal_bool skip_verify = KAL_FALSE;
kal_uint32 file_offset = nvram_param->Offset;
nvram_ldi_ota_header *ota_header;
kal_uint32 nvram_chksum_size = 0;
nvram_lid_chksum_info lid_chksum_info = {0};
#ifdef __NVRAM_LID_CACHE__
kal_bool is_valid_bit = KAL_TRUE;
kal_uint32 m, n;
kal_bool is_only_chksum = KAL_FALSE;
kal_uint32 max_cache_read_size = 0;
#endif
/*----------------------------------------------------------------*/
/* Code Body */
/*----------------------------------------------------------------*/
/* read RAW data directly */
if(NVRAM_IS_ATTR_RAW_DATA(ldi->attr)) {
nvram_param->opid_map |= NVRAM_FS_CMPT_SEEK;
nvram_param->Whence = FS_FILE_CURRENT;
nvram_param->opid_map |= NVRAM_FS_CMPT_READ;
nvram_param->DataPtr = buffer;
nvram_param->Length = rec_size;
nvram_param->Read = &len;
nvram_param->opid_map |= NVRAM_FS_CMPT_CLOSE;
NVRAM_FS_START_EX(FS_OP_CMPTREAD,filename);
result = FS_CMPT_Read(filename, nvram_param);
NVRAM_FS_END(FS_OP_CMPTREAD,result);
if (nvram_param->opid_map != nvram_param->ret[0])
{
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]%s ->FS_CMPT_Read fail at %d \r\n",__FUNCTION__,__LINE__);
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]nvram_param->opid_map(%d) != nvram_param->ret[0](%d) \r\n",nvram_param->opid_map,nvram_param->ret[0]);
nvram_fat_last_err = nvram_param->ret[1];
nvram_fat_last_line = __LINE__;
}
if (len==0)
{
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"%s ->FS_CMPT_Read fail as len=0\r\n",__FUNCTION__);
result = FS_INVALID_FILE_POS; // End of File
nvram_fat_last_line = __LINE__;
}
goto END;
}
nvram_get_lid_chksum_algo_info(ldi, &lid_chksum_info, KAL_FALSE, KAL_FALSE);
nvram_chksum_size = lid_chksum_info.algo_info.chksum_algo_length;
#ifdef __NVRAM_BIND_TO_CHIP_CIPHER__
if ((ldi->attr & NVRAM_ATTR_MSP)||(ldi->attr & NVRAM_ATTR_CONFIDENTIAL))
{
/* 16 byte alignment */
remainLen = NVRAM_MSP_ALIGNMENT_REMAINDER(rec_size + nvram_chksum_size);
}
#else
if (ldi->attr & NVRAM_ATTR_CONFIDENTIAL)
{
/* 16 byte alignment */
remainLen = NVRAM_MSP_ALIGNMENT_REMAINDER(rec_size + nvram_chksum_size);
}
#endif
section_size = rec_size + nvram_chksum_size + remainLen;
nvram_param->opid_map |= NVRAM_FS_CMPT_SEEK;
nvram_param->Offset += (rec_index - 1) * section_size;
nvram_param->Whence = FS_FILE_CURRENT;
/*
//working_buffer_size = MAX_NVRAM_RECORD_SIZE;
//MAX_NVRAM_RECORD_SIZE = (NVRAM_CUSTOM_CFG_MAX_RECORD_SECTOR_NUM * NVRAM_RECORD_SECTOR_SIZE)
// = (128 0r 16 or 4) * 512
*/
working_buffer_size = section_size * rec_amount;
#ifdef __NVRAM_LID_CACHE__
if(working_buffer_size < MD_CCCI_LIMIT_SIZE)
{
max_cache_read_size = MD_CCCI_LIMIT_SIZE;
}
else
{
max_cache_read_size = ((working_buffer_size -1 )/MD_CCCI_LIMIT_SIZE + 1)* MD_CCCI_LIMIT_SIZE;
}
if(max_cache_read_size > MAX_NVRAM_RECORD_SIZE)
{
max_cache_read_size = MAX_NVRAM_RECORD_SIZE;
}
#endif
if (working_buffer_size > MAX_NVRAM_RECORD_SIZE)
{
working_buffer_size = MAX_NVRAM_RECORD_SIZE;
}
// judge read checksum only
if ((type == NVRAM_DRV_READ_TYPE_CHKSUM_ONLY) || (type == NVRAM_DRV_READ_TYPE_CHKSUM_ONLY_2B)) {
//Do not support read checksum only from encrypted
if(ldi->attr & (NVRAM_ATTR_CONFIDENTIAL | NVRAM_ATTR_MSP) ||
(rec_amount * nvram_chksum_size) > MAX_NVRAM_RECORD_SIZE ) {
type = (type==NVRAM_DRV_READ_TYPE_CHKSUM_ONLY_2B)?NVRAM_DRV_READ_TYPE_CHKSUM_2B: NVRAM_DRV_READ_TYPE_CHKSUM;
}
else {
skip_verify = KAL_TRUE;
working_buffer_size = (rec_amount * nvram_chksum_size);
#ifdef __NVRAM_LID_CACHE__
is_only_chksum = KAL_TRUE;
#endif
}
}
#ifdef __NVRAM_LID_CACHE__
working_buffer = (kal_uint8*) get_ctrl_buffer(max_cache_read_size);
#else
working_buffer = (kal_uint8*) get_ctrl_buffer(working_buffer_size);
#endif
// return checksum only
if(skip_verify)
{
if(ldi->attr & NVRAM_ATTR_CHKSUM_INTEGRATE) {
//get appendix header
if(ldi->append_offset == 0) {
ota_header = (nvram_ldi_ota_header *)get_ctrl_buffer(NVRAM_LDI_OTA_HEADER_SIZE);
if(KAL_TRUE == nvram_read_data_header(filename, LDI_HEADER_OTA_SECTION, ota_header, NVRAM_LDI_OTA_HEADER_SIZE) &&
(ota_header->ldi_attr & NVRAM_ATTR_CHKSUM_INTEGRATE) )
{
ldi->append_offset = nvram_appendix_header_offset(ldi);
}
else {
ldi->append_offset = -1;
}
free_ctrl_buffer(ota_header);
}
if(ldi->append_offset > 0) {
nvram_param->opid_map |= NVRAM_FS_CMPT_READ;
nvram_param->Offset = (ldi->append_offset + NVRAM_LDI_APPENDIX_HEADER_SIZE + ((rec_index - 1) * nvram_chksum_size));
nvram_param->DataPtr = working_buffer;
nvram_param->Length = (rec_amount * nvram_chksum_size);
nvram_param->Read = &len;
nvram_param->opid_map |= NVRAM_FS_CMPT_CLOSE;
#ifdef __NVRAM_LID_CACHE__
if (NVRAM_RD_WITH_CACHE(ldi->LID))
{
if (NVRAM_IO_ERRNO_OK != (result = nvram_read_data_from_cache(ldi, nvram_param)))
{
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"%s ->nvram_read_data_from_cache fail,result=%d\r\n",__FUNCTION__,result);
result = FS_ERROR_RESERVED;
nvram_fat_last_line = __LINE__;
}
for(m = 0; m < rec_amount; m++)
{
is_valid_bit = KAL_FALSE;
for(n = 0; n < nvram_chksum_size; n++)
{
if(*(((kal_uint8*)(nvram_param->DataPtr)) + (m * nvram_chksum_size + n)) != 0)
{
is_valid_bit = KAL_TRUE;
break;
}
}
if(is_valid_bit == KAL_FALSE)
{
break;
}
}
if(is_valid_bit == KAL_FALSE)
{
NVRAM_FS_START_EX(FS_OP_CMPTREAD,filename);
result = FS_CMPT_Read(filename, nvram_param);
NVRAM_FS_END(FS_OP_CMPTREAD,result);
if (result == FS_NO_ERROR) {
update_cache_data(ldi, rec_index, rec_amount, nvram_param, is_only_chksum);
}
}
}else
#endif
{
NVRAM_FS_START_EX(FS_OP_CMPTREAD,filename);
result = FS_CMPT_Read(filename, nvram_param);
NVRAM_FS_END(FS_OP_CMPTREAD,result);
}
if ((nvram_param->opid_map != nvram_param->ret[0]) || (len==0))
{
//goto normal read flow when read appendix fail
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]%s ->FS_CMPT_Read fail at %d\r\n",__FUNCTION__,__LINE__);
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]nvram_param->opid_map(%d) != nvram_param->ret[0](%d) or len==%d \r\n",nvram_param->opid_map,nvram_param->ret[0],len);
goto NO_CHKSUM_INTEGRATE;
}
}
else {
goto NO_CHKSUM_INTEGRATE;
}
}
else {
NO_CHKSUM_INTEGRATE:
for (j = 0; j < rec_amount; j++)
{
nvram_param->opid_map |= NVRAM_FS_CMPT_READ;
/*
1, will be a full process: fs_open() ==> fs_seek(, offsert) ==> fs_read() ==> fs_close()
2, offset should be right
*/
nvram_param->Offset = file_offset + (rec_size + ((j + rec_index - 1) * section_size));
nvram_param->DataPtr = (working_buffer + (j* nvram_chksum_size));
nvram_param->Length = nvram_chksum_size;
nvram_param->Read = &len;
nvram_param->opid_map |= NVRAM_FS_CMPT_CLOSE;
#ifdef __NVRAM_LID_CACHE__
if (NVRAM_RD_WITH_CACHE(ldi->LID))
{
result = nvram_read_data_from_cache(ldi, nvram_param);
is_valid_bit = KAL_FALSE;
for(n = 0; n < nvram_chksum_size; n++)
{
if(*(((kal_uint8*)(nvram_param->DataPtr)) + n) != 0)
{
is_valid_bit = KAL_TRUE;
break;
}
}
if (is_valid_bit == KAL_FALSE)
{
NVRAM_FS_START_EX(FS_OP_CMPTREAD,filename);
result = FS_CMPT_Read(filename, nvram_param);
NVRAM_FS_END(FS_OP_CMPTREAD,result);
if (result == FS_NO_ERROR) {
update_cache_data(ldi, rec_index+j, 1, nvram_param, is_only_chksum);
}
}
}else
#endif
{
NVRAM_FS_START_EX(FS_OP_CMPTREAD,filename);
result = FS_CMPT_Read(filename, nvram_param);
NVRAM_FS_END(FS_OP_CMPTREAD,result);
}
if (nvram_param->opid_map != nvram_param->ret[0])
{
nvram_fat_last_err = nvram_param->ret[1];
nvram_fat_last_line = __LINE__;
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]%s->FS_CMPT_Read fail at %d\r\n",__FUNCTION__,__LINE__);
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]nvram_param->opid_map(%d) != nvram_param->ret[0](%d)\r\n",nvram_param->opid_map,nvram_param->ret[0]);
goto final;
}
if (len==0)
{
result = FS_INVALID_FILE_POS; // End of File
nvram_fat_last_line = __LINE__;
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]%s->FS_CMPT_Read fail at %d,len=0\r\n",__FUNCTION__,__LINE__);
goto final;
}
}
}
//Caculate checksum
if(type == NVRAM_DRV_READ_TYPE_CHKSUM_ONLY_2B) {
for (j = 0; j < rec_amount; j++) {
chksum3 = nvram_util_md5_checksum_convert((working_buffer + (j* nvram_chksum_size)), NULL, KAL_TRUE);
kal_mem_cpy(buffer + (NVRAM_CHKSUM_SIZE_2B* j), &chksum3, NVRAM_CHKSUM_SIZE_2B);
}
}
else {
kal_mem_cpy(buffer, working_buffer, (rec_amount * nvram_chksum_size));
}
}
else
{
kal_int32 rec_in_block = working_buffer_size / section_size;
#ifdef __NVRAM_LID_CACHE__
kal_uint32 rec_cnt_for_cache_read = 0;
kal_uint32 rec_index_for_cache_read = 0;
kal_uint32 cache_read_length = 0;
kal_int32 rec_in_block_for_cache_read = max_cache_read_size / section_size;
kal_uint32 nvram_param_offset_temp = 0;
void *DataPtr_temp = NULL;
#endif
chksum1 = (kal_uint8*) get_ctrl_buffer(nvram_chksum_size);
for (i = 0 ; i < rec_amount; )
{
kal_uint32 total_read = section_size * rec_in_block;
kal_uint32 working_buffer_sub_index = 0;
nvram_param->Offset = file_offset + (rec_index - 1) * section_size;
nvram_param->Offset += (i*section_size);
#ifdef __NVRAM_LID_CACHE__
is_valid_bit = KAL_TRUE;
#endif
/* last read */
if (rec_in_block > rec_amount - i)
{
rec_in_block = rec_amount - i;
total_read = section_size * rec_in_block;
}
len = 0;
do
{
nvram_param->opid_map |= NVRAM_FS_CMPT_READ;
/*
1, will be a full process: fs_open() ==> fs_seek(, offsert) ==> fs_read() ==> fs_close()
2, offset should be right
*/
nvram_param->Offset += len;
nvram_param->DataPtr = (working_buffer + working_buffer_sub_index);
nvram_param->Length = total_read;
nvram_param->Read = &len;
nvram_param->opid_map |= NVRAM_FS_CMPT_CLOSE;
#ifdef __NVRAM_LID_CACHE__
is_valid_bit = KAL_TRUE;
nvram_param_offset_temp = nvram_param->Offset;
//DataPtr_temp = nvram_param->DataPtr;
cache_read_length = total_read;
if (NVRAM_RD_WITH_CACHE(ldi->LID))
{
int n;
rec_cnt_for_cache_read = rec_in_block_for_cache_read;
for( n = 0; n < rec_in_block; n++)
{
if (!check_valid_bit_by_ltable_entry(ldi, rec_index+i+n))
{
rec_index_for_cache_read = rec_index +i+n;
if(rec_index+i+n + rec_in_block_for_cache_read > ldi->total_records)
{
rec_cnt_for_cache_read = ldi->total_records - (rec_index+i+n )+1;
}
is_valid_bit = KAL_FALSE;
break;
}
}
if(!is_valid_bit)
{
DataPtr_temp = (kal_uint8*) get_ctrl_buffer(rec_cnt_for_cache_read * section_size);
nvram_param->Offset += ((rec_index_for_cache_read- rec_index- i) * (section_size));
nvram_param->DataPtr = DataPtr_temp;
nvram_param->Length = rec_cnt_for_cache_read * section_size;
NVRAM_FS_START_EX(FS_OP_CMPTREAD,filename);
result = FS_CMPT_Read(filename,nvram_param);
NVRAM_FS_END(FS_OP_CMPTREAD,result);
if (nvram_param->opid_map != nvram_param->ret[0])
{
free_ctrl_buffer(DataPtr_temp);
DataPtr_temp = NULL;
nvram_fat_last_err = nvram_param->ret[1];
nvram_fat_last_line = __LINE__;
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]%s ->FS_CMPT_Read fail at %d\r\n",__FUNCTION__,__LINE__);
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]nvram_param->opid_map(%d) != nvram_param->ret[0](%d)\r\n",nvram_param->opid_map,nvram_param->ret[0]);
goto final;
}
if (len != nvram_param->Length)
{
free_ctrl_buffer(DataPtr_temp);
DataPtr_temp = NULL;
result = FS_INVALID_FILE_POS; // End of File
nvram_fat_last_line = __LINE__;
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]%s ->FS_CMPT_Read fail at %d\r\n",__FUNCTION__,__LINE__);
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]len(%d) != %d\r\n",len, nvram_param->Length);
goto final;
}
update_cache_data(ldi, rec_index_for_cache_read, rec_cnt_for_cache_read, nvram_param, is_only_chksum);
mask_valid_bit_by_ltable_entry(ldi, rec_index_for_cache_read, rec_cnt_for_cache_read);
free_ctrl_buffer(DataPtr_temp);
DataPtr_temp = NULL;
}
nvram_param->Offset = nvram_param_offset_temp;
nvram_param->DataPtr = (working_buffer + working_buffer_sub_index);
nvram_param->Length = cache_read_length;
len = total_read;
nvram_read_data_from_cache(ldi, nvram_param);
}
else
#endif
{
NVRAM_FS_START_EX(FS_OP_CMPTREAD,filename);
result = FS_CMPT_Read(filename, nvram_param);
NVRAM_FS_END(FS_OP_CMPTREAD,result);
if (nvram_param->opid_map != nvram_param->ret[0])
{
nvram_fat_last_err = nvram_param->ret[1];
nvram_fat_last_line = __LINE__;
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]%s ->FS_CMPT_Read fail at %d\r\n",__FUNCTION__,__LINE__);
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]nvram_param->opid_map(%d) != nvram_param->ret[0](%d)\r\n",nvram_param->opid_map,nvram_param->ret[0]);
goto final;
}
if (len == 0)
{
result = FS_INVALID_FILE_POS; // End of File
nvram_fat_last_line = __LINE__;
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]%s->FS_CMPT_Read fail at %d,len=0\r\n",__FUNCTION__,__LINE__);
goto final;
}
}
total_read -= len;
working_buffer_sub_index += len;
}while(total_read > 0);
#ifdef __NVRAM_CRYPT_TEST__
if (bReadMsp == 1)
{
kal_mem_cpy(&NVRAM_EF_MSP_TEST_R, working_buffer, NVRAM_MSP_TEST_LEN);
}
#endif
#ifdef __NVRAM_BIND_TO_CHIP_CIPHER__
if (ldi->attr & NVRAM_ATTR_MSP)
{
for (j = 0; j < rec_in_block; j++)
{
/* work arround solution for hw.. sej is not stable */
#ifdef __CCCIFS_SUPPORT__
kal_uint8 *working_buffer2 = (kal_uint8*) get_ctrl_buffer(section_size);
kal_uint8 *working_buffer3 = (kal_uint8*) get_ctrl_buffer(section_size);
//copy the encrypted data from working_buffer to working_buffer2
memcpy(working_buffer2, working_buffer + section_size * j, section_size);
do
{
nvram_trace_to_file(__LINE__, 999, 1, 0, 0 ,0);
nvram_trace_to_file(nvram_ptr->secret_key[0], nvram_ptr->secret_key[1], nvram_ptr->secret_key[2], nvram_ptr->secret_key[3], 0, 0);
nvram_trace_to_file(working_buffer[j*section_size], working_buffer[j*section_size + 1], working_buffer[j*section_size + 2], working_buffer[j*section_size + 3], 0, 0);
//decrypt the working_buffer
SST_Secure_Algo(NVRAM_MSP_DECRYPT, (kal_uint32) (working_buffer + section_size * j), section_size, nvram_ptr->secret_key, working_buffer + section_size * j);
nvram_trace_to_file(working_buffer[j*section_size], working_buffer[j*section_size + 1], working_buffer[j*section_size + 2], working_buffer[j*section_size + 3], 0, 0);
//copy decrypted data from working_buffer to working_buffer3
memcpy(working_buffer3, working_buffer + section_size * j, section_size);
//encrypt the working_buffer3
SST_Secure_Algo(NVRAM_MSP_ENCRYPT, (kal_uint32)working_buffer3, section_size, nvram_ptr->secret_key, working_buffer3);
//compare the working_buffer2 & working_buffer3
if (memcmp(working_buffer2, working_buffer3, section_size) == 0)
{
//decrypt PASS
break;
}
else
{
//decrypt FAIL, try again
memcpy(working_buffer + section_size * j, working_buffer2, section_size);
}
}while(1);
free_ctrl_buffer(working_buffer2);
free_ctrl_buffer(working_buffer3);
working_buffer2 = NULL;
working_buffer3 = NULL;
#else
SST_Secure_Algo(NVRAM_MSP_DECRYPT, (kal_uint32) (working_buffer + section_size * j), section_size, nvram_ptr->secret_key, working_buffer + section_size * j);
#endif
}
}
#endif
#ifdef __NVRAM_CRYPT_TEST__
if (bReadMsp == 1)
{
kal_mem_cpy(&NVRAM_EF_MSP_TEST_R[NVRAM_MSP_TEST_LEN],working_buffer,NVRAM_MSP_TEST_LEN);
}
#endif
/* Handle multi-record reading */
for (j = 0; j < rec_in_block; j++)
{
if (ldi->attr & NVRAM_ATTR_CONFIDENTIAL)
{
// custom_nvram_decrypt(nvram_ptr->secret_key, working_buffer + section_size * j, rec_size, rec_size);
nvram_AES_decrypt(working_buffer + section_size * j, section_size);
}
//get checksum from the working buffer
chksum2 = (kal_uint8*) (working_buffer + section_size * j + rec_size);
//calculate the checksum from the content
/* checksum from content */
kal_mem_set(chksum1, 0, nvram_chksum_size);
nvram_util_caculate_checksum(ldi, working_buffer + (section_size * j), rec_size, chksum1);
if (kal_mem_cmp(chksum1, chksum2, nvram_chksum_size)!=0)
{
nvram_ptr->sw_status &= NVRAM_SW_SOME_CORRUPT;
if(nvram_ee_info != NULL){
nvram_ee_info->nvram_init_context.sw_status = nvram_ptr->sw_status;
}
#ifdef __NVRAM_LID_CACHE__
if (NVRAM_RD_WITH_CACHE(ldi->LID))
{
unmask_valid_bit_by_ltable_entry(ldi, 0, (ldi->total_records + 1));
}
#endif
nvram_fat_last_line = __LINE__;
result = NVRAM_DRV_CHECKSUM_ERROR;
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]%s Checksum error at %d\r\n",__FUNCTION__,__LINE__);
goto final;
}
//seems no need to calculate checksum3, and buffer for NVRAM_DRV_READ_TYPE_CHKSUM_2B is useless if we do not verify the checksum?
//if we want to compare the checksum between A & B, we need another buffer to use memcmp
/* checksum after decrypt */
#ifdef __NV_CHKSUM_ENHANCE__
if(lid_chksum_info.algo_info.chksum_algo_type == NVRAM_MD5)
{
kal_mem_set(chksum1, 0, nvram_chksum_size);
chksum3 = nvram_util_caculate_checksum(ldi, working_buffer + (section_size * j), rec_size, chksum1);
}
#else
chksum3 = nvram_util_caculate_checksum(ldi, working_buffer + (section_size * j), rec_size, chksum1);
#endif
if (type == NVRAM_DRV_READ_TYPE_DATA)
{
kal_mem_cpy(buffer + (rec_size * (i + j)), working_buffer + (section_size * j), rec_size);
}
else if ((type == NVRAM_DRV_READ_TYPE_CHKSUM_2B)||(type == NVRAM_DRV_READ_TYPE_CHKSUM_ONLY_2B))
{
kal_mem_cpy(buffer + (NVRAM_CHKSUM_SIZE_2B * (i + j)), &chksum3, NVRAM_CHKSUM_SIZE_2B);
}
else if ((type == NVRAM_DRV_READ_TYPE_CHKSUM)||(type == NVRAM_DRV_READ_TYPE_CHKSUM_ONLY))
{
kal_mem_cpy(buffer + (nvram_chksum_size * (i + j)), chksum2, nvram_chksum_size);
}
}
#ifdef __NVRAM_CRYPT_TEST__
if (bReadMsp == 1)
{
kal_mem_cpy(&NVRAM_EF_MSP_TEST_R[NVRAM_MSP_TEST_LEN*2],working_buffer,NVRAM_MSP_TEST_LEN);
nvram_create_report_msp_file(KAL_FALSE);
}
#endif
i += rec_in_block;
}
}
final:
if(chksum1)
{
free_ctrl_buffer(chksum1);
chksum1 = NULL;
}
if (working_buffer)
{
free_ctrl_buffer(working_buffer);
working_buffer = NULL;
}
END:
if (FS_NO_ERROR > result)
{
nvram_fat_last_err = result;
MD_TRC_FUNC_NVRAM_DRV_FAT_THROW_EXCEPTION(nvram_fat_last_err, nvram_fat_last_line);
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]%s fail at %d status %d\r\n",__FUNCTION__,nvram_fat_last_line,nvram_fat_last_err);
}
return result;
}
#endif
/*****************************************************************************
* FUNCTION
* nvram_drv_fat_read_aux
* DESCRIPTION
* read record(s) from FAT.
* PARAMETERS
* hFile [IN] file handle
* rec_index [IN] which record to read (start)
* rec_amount [IN] how many record to read at once
* rec_size [IN] size of record
* buffer [IN/OUT] buffer of check sum
* type [IN] read content or checksum
* ismsp [IN] to indicate that the records protected by hw
* RETURNS
* = 0: success
* > 0: NVRAM error code
* < 0: FS error code
*****************************************************************************/
kal_int32 nvram_drv_fat_read_section(
FS_HANDLE hFile,
kal_uint16 rec_index,
kal_uint16 rec_amount,
kal_uint32 rec_size,
kal_uint8 *buffer,
nvram_drv_read_type_enum type,
nvram_ltable_entry_struct *ldi)
{
/*----------------------------------------------------------------*/
/* Local Variables */
/*----------------------------------------------------------------*/
kal_uint16 chksum3 = 0;
kal_uint8 *chksum1 = NULL;
kal_uint8 *chksum2 = NULL;
kal_uint32 len = 0, remainLen = 0;
kal_uint32 section_size;
kal_uint32 working_buffer_size;
kal_uint8 *working_buffer = NULL;
kal_int32 result = NVRAM_DRV_OK;
kal_uint32 i,j;
kal_bool skip_verify = KAL_FALSE;
nvram_ldi_ota_header *ota_header;
kal_uint32 seek_offset = 0;
kal_uint32 nvram_chksum_size = 0;
nvram_lid_chksum_info lid_chksum_info = {0};
/*----------------------------------------------------------------*/
/* Code Body */
/*----------------------------------------------------------------*/
/* read RAW data directly */
if(NVRAM_IS_ATTR_RAW_DATA(ldi->attr)) {
NVRAM_FS_START(FS_OP_READ);
result = FS_Read(hFile, buffer, rec_size, &len);
NVRAM_FS_END(FS_OP_READ,result);
if (FS_NO_ERROR > result)
{
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]%s->FS_Read error at %d,result=%d\r\n",__FUNCTION__,__LINE__,result);
nvram_fat_last_line = __LINE__;
}
goto ERROR;
}
nvram_get_lid_chksum_algo_info(ldi, &lid_chksum_info, KAL_FALSE, KAL_FALSE);
nvram_chksum_size = lid_chksum_info.algo_info.chksum_algo_length;
#ifdef __NVRAM_BIND_TO_CHIP_CIPHER__
if ((ldi->attr & NVRAM_ATTR_MSP)||(ldi->attr & NVRAM_ATTR_CONFIDENTIAL))
{
/* 16 byte alignment */
remainLen = NVRAM_MSP_ALIGNMENT_REMAINDER(rec_size + nvram_chksum_size);
}
#else
if (ldi->attr & NVRAM_ATTR_CONFIDENTIAL)
{
/* 16 byte alignment */
remainLen = NVRAM_MSP_ALIGNMENT_REMAINDER(rec_size + nvram_chksum_size);
}
#endif
section_size = rec_size + nvram_chksum_size + remainLen;
/* seek to the record start */
NVRAM_FS_START(FS_OP_SEEK);
result = FS_Seek(hFile, (rec_index - 1) * section_size, FS_FILE_CURRENT);
NVRAM_FS_END(FS_OP_SEEK,result);
if (FS_NO_ERROR > result)
{
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]%s->FS_Seek error at %d,result=%d\r\n",__FUNCTION__,__LINE__,result);
nvram_fat_last_line = __LINE__;
goto ERROR;
}
//working_buffer_size = MAX_NVRAM_RECORD_SIZE;
//MAX_NVRAM_RECORD_SIZE = (NVRAM_CUSTOM_CFG_MAX_RECORD_SECTOR_NUM * NVRAM_RECORD_SECTOR_SIZE)
// = (16 or 4) * 512
working_buffer_size = section_size * rec_amount;
if (working_buffer_size > MAX_NVRAM_RECORD_SIZE)
{
working_buffer_size = MAX_NVRAM_RECORD_SIZE;
}
// judge read checksum only
if ((type == NVRAM_DRV_READ_TYPE_CHKSUM_ONLY) || (type == NVRAM_DRV_READ_TYPE_CHKSUM_ONLY_2B)) {
//Do not support read checksum only from encrypted
if(ldi->attr & (NVRAM_ATTR_CONFIDENTIAL | NVRAM_ATTR_MSP) ||
(rec_amount * nvram_chksum_size) > MAX_NVRAM_RECORD_SIZE ) {
type = (type==NVRAM_DRV_READ_TYPE_CHKSUM_ONLY_2B)?NVRAM_DRV_READ_TYPE_CHKSUM_2B: NVRAM_DRV_READ_TYPE_CHKSUM;
}
else {
skip_verify = KAL_TRUE;
working_buffer_size = (rec_amount * nvram_chksum_size);
}
}
working_buffer = (kal_uint8*) get_ctrl_buffer(working_buffer_size);
if(skip_verify)
{
if(ldi->attr & NVRAM_ATTR_CHKSUM_INTEGRATE) {
//get appendix header
if(ldi->append_offset == 0) {
NVRAM_FS_START(FS_OP_SEEK);
seek_offset = FS_Seek(hFile, 0, FS_FILE_CURRENT); //backup FS offset
NVRAM_FS_END(FS_OP_SEEK,seek_offset);
ota_header = (nvram_ldi_ota_header *)get_ctrl_buffer(NVRAM_LDI_OTA_HEADER_SIZE);
if(KAL_TRUE == nvram_read_ota_header(hFile, ota_header, NVRAM_LDI_OTA_HEADER_SIZE) &&
(ota_header->ldi_attr & NVRAM_ATTR_CHKSUM_INTEGRATE) )
{
ldi->append_offset = nvram_appendix_header_offset(ldi);
}
else {
ldi->append_offset = -1;
}
free_ctrl_buffer(ota_header);
ota_header = NULL;
}
if(ldi->append_offset > 0) {
if(!seek_offset) {
//backup FS offset
NVRAM_FS_START(FS_OP_SEEK);
seek_offset = FS_Seek(hFile, 0, FS_FILE_CURRENT);
NVRAM_FS_END(FS_OP_SEEK,seek_offset);
}
NVRAM_FS_START(FS_OP_SEEK);
result = FS_Seek(hFile, (ldi->append_offset + NVRAM_LDI_APPENDIX_HEADER_SIZE + ((rec_index - 1) * nvram_chksum_size)), FS_FILE_BEGIN);
NVRAM_FS_END(FS_OP_SEEK,result);
if(FS_NO_ERROR > result)
{
//goto normal read flow when read appendix fail
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]%s ->FS_Seek error at %d,result=%d\r\n",__FUNCTION__,__LINE__,result);
goto NO_CHKSUM_INTEGRATE;
}
NVRAM_FS_START(FS_OP_READ);
result = FS_Read(hFile, working_buffer, (rec_amount * nvram_chksum_size), &len);
NVRAM_FS_END(FS_OP_READ,result);
if (FS_NO_ERROR > result)
{
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]%s ->FS_Read error at %d,result=%d\r\n",__FUNCTION__,__LINE__,result);
goto NO_CHKSUM_INTEGRATE;
}
}
else {
goto NO_CHKSUM_INTEGRATE;
}
}
else {
NO_CHKSUM_INTEGRATE:
if(seek_offset) {
//Restore FS ptr
NVRAM_FS_START(FS_OP_SEEK);
result = FS_Seek(hFile, seek_offset, FS_FILE_BEGIN);
NVRAM_FS_END(FS_OP_SEEK,result);
}
for (j = 0; j < rec_amount; j++)
{
/* seek to the record checksum */
NVRAM_FS_START(FS_OP_SEEK);
result = FS_Seek(hFile, rec_size, FS_FILE_CURRENT);
NVRAM_FS_END(FS_OP_SEEK,result);
if(FS_NO_ERROR > result)
{
nvram_fat_last_line = __LINE__;
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]%s ->FS_Seek error at %d,result=%d\r\n",__FUNCTION__,__LINE__,result);
goto ERROR;
}
NVRAM_FS_START(FS_OP_READ);
result = FS_Read(hFile, (working_buffer + (j* nvram_chksum_size)), nvram_chksum_size, &len);
NVRAM_FS_END(FS_OP_READ,result);
if (FS_NO_ERROR > result)
{
nvram_fat_last_line = __LINE__;
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]%s ->FS_Read error at %d,result=%d\r\n",__FUNCTION__,__LINE__,result);
goto final;
}
}
}
//Caculate checksum
if(type == NVRAM_DRV_READ_TYPE_CHKSUM_ONLY_2B) {
for (j = 0; j < rec_amount; j++) {
chksum3 = nvram_util_md5_checksum_convert((working_buffer + (j* nvram_chksum_size)), NULL, KAL_TRUE);
kal_mem_cpy(buffer + (NVRAM_CHKSUM_SIZE_2B* j), &chksum3, NVRAM_CHKSUM_SIZE_2B);
}
}
else {
kal_mem_cpy(buffer, working_buffer, (rec_amount * nvram_chksum_size));
}
}
else
{
kal_int32 rec_in_block = working_buffer_size / section_size;
chksum1 = (kal_uint8*) get_ctrl_buffer(nvram_chksum_size);
for (i = 0 ; i < rec_amount; )
{
kal_uint32 total_read = section_size * rec_in_block;
kal_uint32 working_buffer_sub_index = 0;
/* last read */
if (rec_in_block > rec_amount - i)
{
rec_in_block = rec_amount - i;
}
#define NVRAM_MAX_READ_LEN (3*1024)
do
{
kal_uint32 this_read = total_read;
if (total_read >= NVRAM_MAX_READ_LEN)
{
this_read = NVRAM_MAX_READ_LEN;
}
NVRAM_FS_START(FS_OP_READ);
result = FS_Read(hFile, working_buffer + working_buffer_sub_index, this_read, &len);
NVRAM_FS_END(FS_OP_READ,result);
if (FS_NO_ERROR > result)
{
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]%s ->FS_Read error at %d,result=%d\r\n",__FUNCTION__,__LINE__,result);
nvram_fat_last_line = __LINE__;
goto final;
}
if (len==0)
{
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]%s ->FS_Read error at %d,len=0\r\n",__FUNCTION__,__LINE__);
result = FS_INVALID_FILE_POS; // End of File
nvram_fat_last_line = __LINE__;
goto final;
}
total_read -= len;
working_buffer_sub_index += len;
}while(total_read > 0);
#ifdef __NVRAM_BIND_TO_CHIP_CIPHER__
if (ldi->attr & NVRAM_ATTR_MSP)
{
for (j = 0; j < rec_in_block; j++)
{
/* work arround solution for hw.. sej is not stable */
#ifdef __CCCIFS_SUPPORT__
kal_uint8 *working_buffer2 = (kal_uint8*) get_ctrl_buffer(section_size);
kal_uint8 *working_buffer3 = (kal_uint8*) get_ctrl_buffer(section_size);
//copy the encrypted data from working_buffer to working_buffer2
memcpy(working_buffer2, working_buffer + section_size * j, section_size);
do
{
nvram_trace_to_file(__LINE__, 999, 1, 0, 0 ,0);
nvram_trace_to_file(nvram_ptr->secret_key[0], nvram_ptr->secret_key[1], nvram_ptr->secret_key[2], nvram_ptr->secret_key[3], 0, 0);
nvram_trace_to_file(working_buffer[j*section_size], working_buffer[j*section_size + 1], working_buffer[j*section_size + 2], working_buffer[j*section_size + 3], 0, 0);
//decrypt the working_buffer
SST_Secure_Algo(NVRAM_MSP_DECRYPT, (kal_uint32) (working_buffer + section_size * j), section_size, nvram_ptr->secret_key, working_buffer + section_size * j);
nvram_trace_to_file(working_buffer[j*section_size], working_buffer[j*section_size + 1], working_buffer[j*section_size + 2], working_buffer[j*section_size + 3], 0, 0);
//copy decrypted data from working_buffer to working_buffer3
memcpy(working_buffer3, working_buffer + section_size * j, section_size);
//encrypt the working_buffer3
SST_Secure_Algo(NVRAM_MSP_ENCRYPT, (kal_uint32)working_buffer3, section_size, nvram_ptr->secret_key, working_buffer3);
//compare the working_buffer2 & working_buffer3
if (memcmp(working_buffer2, working_buffer3, section_size) == 0)
{
//decrypt PASS
break;
}
else
{
//decrypt FAIL, try again
memcpy(working_buffer + section_size * j, working_buffer2, section_size);
}
}while(1);
free_ctrl_buffer(working_buffer2);
free_ctrl_buffer(working_buffer3);
working_buffer2 = NULL;
working_buffer3 = NULL;
#else
SST_Secure_Algo(NVRAM_MSP_DECRYPT, (kal_uint32) (working_buffer + section_size * j), section_size, nvram_ptr->secret_key, working_buffer + section_size * j);
#endif
}
}
#endif
/* Handle multi-record reading */
for (j = 0; j < rec_in_block; j++)
{
if (ldi->attr & NVRAM_ATTR_CONFIDENTIAL)
{
// custom_nvram_decrypt(nvram_ptr->secret_key, working_buffer + section_size * j, rec_size, rec_size);
nvram_AES_decrypt(working_buffer + section_size * j, section_size);
}
//verify checksum one at once
//get checksum from the working buffer
chksum2 = (kal_uint8*) (working_buffer + section_size * j + rec_size);
//calculate the checksum from the content
/* checksum from content */
kal_mem_set(chksum1, 0, nvram_chksum_size);
nvram_util_caculate_checksum(ldi, working_buffer + (section_size * j), rec_size,chksum1);
if (kal_mem_cmp(chksum1, chksum2, nvram_chksum_size)!=0)
{
nvram_ptr->sw_status &= NVRAM_SW_SOME_CORRUPT;
if(nvram_ee_info != NULL){
nvram_ee_info->nvram_init_context.sw_status = nvram_ptr->sw_status;
}
nvram_fat_last_line = __LINE__;
result = NVRAM_DRV_CHECKSUM_ERROR;
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]%s Checksum error at %d\r\n",__FUNCTION__,__LINE__);
goto final;
}
//seems no need to calculate checksum3, and buffer for NVRAM_DRV_READ_TYPE_CHKSUM_2B is useless if we do not verify the checksum?
//if we want to compare the checksum between A & B, we need another buffer to use memcmp
/* checksum after decrypt */
#ifdef __NV_CHKSUM_ENHANCE__
if(lid_chksum_info.algo_info.chksum_algo_type== NVRAM_MD5)
{
kal_mem_set(chksum1, 0, nvram_chksum_size);
chksum3 = nvram_util_caculate_checksum(ldi, working_buffer + (section_size * j), rec_size,chksum1);
}
#else
chksum3 = nvram_util_caculate_checksum(ldi, working_buffer + (section_size * j), rec_size,chksum1);
#endif
if (type == NVRAM_DRV_READ_TYPE_DATA)
{
kal_mem_cpy(buffer + (rec_size * (i + j)), working_buffer + (section_size * j), rec_size);
}
else if((type == NVRAM_DRV_READ_TYPE_CHKSUM_2B)||(type == NVRAM_DRV_READ_TYPE_CHKSUM_ONLY_2B))
{
kal_mem_cpy(buffer + (NVRAM_CHKSUM_SIZE_2B * (i + j)), &chksum3, NVRAM_CHKSUM_SIZE_2B);
}
else if ((type == NVRAM_DRV_READ_TYPE_CHKSUM)||(type == NVRAM_DRV_READ_TYPE_CHKSUM_ONLY))
{
kal_mem_cpy(buffer + (nvram_chksum_size * (i + j)), chksum1, nvram_chksum_size);
}
}
i += rec_in_block;
}
}
final:
if(chksum1)
{
free_ctrl_buffer(chksum1);
chksum1 = NULL;
}
if (working_buffer)
{
free_ctrl_buffer(working_buffer);
working_buffer = NULL;
}
ERROR:
if (FS_NO_ERROR > result)
{
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]%s fail at %d,result=%d\r\n",__FUNCTION__,__LINE__,result);
nvram_fat_last_err = result;
MD_TRC_FUNC_NVRAM_DRV_FAT_THROW_EXCEPTION(nvram_fat_last_err, nvram_fat_last_line);
}
return result;
}
/*****************************************************************************
* FUNCTION
* nvram_drv_fat_read_aux
* DESCRIPTION
* read record(s) from FAT.
* PARAMETERS
* filename [IN] full path of the data item
* rec_index [IN] which record to read (start)
* rec_amount [IN] how many record to read at once
* rec_size [IN] size of record
* buffer [IN/OUT] buffer of check sum
* type [IN] read content or checksum
* ismsp [IN] to indicate that the records protected by hw
* RETURNS
* = 0: success
* > 0: NVRAM error code
* < 0: FS error code
*****************************************************************************/
kal_int32 nvram_drv_fat_read(
kal_char *nvramname,
nvram_folder_enum nvram_folder, /* folder index */
kal_uint32 file_offset,
kal_uint16 rec_index,
kal_uint16 rec_amount,
kal_uint32 rec_size,
kal_uint8 *buffer,
nvram_drv_read_type_enum type,
nvram_ltable_entry_struct *ldi)
{
/*----------------------------------------------------------------*/
/* Local Variables */
/*----------------------------------------------------------------*/
FS_HANDLE hFile = 0;
kal_uint32 len = 0;
kal_int32 result = 0;
kal_wchar filename[NVRAM_MAX_PATH_LEN];
#if defined(__NVRAM_ACCESS_TIMEOUT_ASSERT__)
SGPT_CTRL_START_T start;
#endif
#if (defined(__NVRAM_FS_OPERATION_COMPACT__) && defined(__CCCIFS_SUPPORT__) && defined(__MTK_TARGET__)) || defined(__NVRAM_FS_CMPT_SIMULATION__)
NVRAM_FS_PARAM_CMPT_T nvram_param = {0};
#else
kal_int32 ret = 0;
#endif
/*----------------------------------------------------------------*/
/* Code Body */
/*----------------------------------------------------------------*/
/* NVRAM GPT timeout assert start timer */
#if defined(__NVRAM_ACCESS_TIMEOUT_ASSERT__)
start.u2Tick= NVRAM_READ_GPT_TIMEOUT;
start.pfCallback=nvram_gpt_timeout_callback;
start.vPara=NULL;
#endif
nvram_util_take_mutex(g_nvram_fs_mutex);
#if defined(__NVRAM_ACCESS_TIMEOUT_ASSERT__)
DclSGPT_Control(nvram_gpt_handle, SGPT_CMD_START, (DCL_CTRL_DATA_T*)&start); //start timer
#endif
do
{
if (rec_index < 1)
{
nvram_fat_last_line = __LINE__;
result = NVRAM_DRV_INVALID_RECORD_ID;
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error] invalid record index(%d) \r\n",rec_index);
break;
}
nvram_query_file_name(nvram_folder, nvramname, filename);
#if !defined(__NVRAM_FS_OPERATION_COMPACT__) || defined(__NVRAM_PSEUDO_MERGE__) || !((defined(__CCCIFS_SUPPORT__) && defined(__MTK_TARGET__)) || defined(__NVRAM_FS_CMPT_SIMULATION__))
NVRAM_FS_START_EX(FS_OP_OPEN,filename);
hFile = FS_Open((const kal_wchar*)filename, FS_READ_ONLY | FS_OPEN_NO_DIR | FS_OPEN_SHARED);
NVRAM_FS_END(FS_OP_OPEN,hFile);
if (hFile == FS_FILE_NOT_FOUND)
{
nvram_fat_last_line = __LINE__;
result = NVRAM_DRV_EMPTY_RECORD;
break;
}
else if (hFile <= FS_NO_ERROR)
{
nvram_fat_last_line = __LINE__;
result = NVRAM_DRV_FATAL_ERROR;
break;
}
/* check if a empty record */
NVRAM_FS_START(FS_OP_GETFILESIZE);
result = FS_GetFileSize(hFile, &len);
NVRAM_FS_END(FS_OP_GETFILESIZE,result);
if ((result == FS_NO_ERROR) && (len == 0))
{
NVRAM_FS_START(FS_OP_CLOSE);
ret = FS_Close(hFile);
NVRAM_FS_END(FS_OP_CLOSE,ret);
nvram_fat_last_line = __LINE__;
result = NVRAM_DRV_EMPTY_RECORD;
break;
}
NVRAM_FS_START(FS_OP_SEEK);
result = FS_Seek(hFile, file_offset, FS_FILE_BEGIN);
NVRAM_FS_END(FS_OP_SEEK,result);
if (FS_NO_ERROR > result)
{
NVRAM_FS_START(FS_OP_CLOSE);
ret = FS_Close(hFile);
NVRAM_FS_END(FS_OP_CLOSE,ret);
nvram_fat_last_line = __LINE__;
break;
}
result = nvram_drv_fat_read_section(hFile, rec_index, rec_amount, rec_size, buffer, type, ldi);
if (hFile > FS_NO_ERROR)
{
NVRAM_FS_START(FS_OP_CLOSE);
ret = FS_Close(hFile);
NVRAM_FS_END(FS_OP_CLOSE,ret);
}
#else
nvram_param.opid_map = 0;
nvram_param.ret[0] = 0;
nvram_param.ret[1] = 0;
nvram_param.Flag = (FS_READ_ONLY | FS_OPEN_NO_DIR | FS_OPEN_SHARED);
nvram_param.opid_map |= NVRAM_FS_CMPT_OPEN;
nvram_param.opid_map |= NVRAM_FS_CMPT_GETFILESIZE;
nvram_param.FileSize = &len;
nvram_param.Offset = file_offset;
result = nvram_drv_fat_read_section_cmpt(hFile, rec_index, rec_amount, rec_size, buffer, type, ldi,(kal_wchar*)filename, &nvram_param);
#endif
}while(0);
#if defined(__NVRAM_ACCESS_TIMEOUT_ASSERT__)
DclSGPT_Control(nvram_gpt_handle, SGPT_CMD_STOP, (DCL_CTRL_DATA_T*)NULL); //stop timer
#endif
nvram_util_give_mutex(g_nvram_fs_mutex);
#if !defined(__NVRAM_FS_OPERATION_COMPACT__) || defined(__NVRAM_PSEUDO_MERGE__) || !((defined(__CCCIFS_SUPPORT__) && defined(__MTK_TARGET__)) || defined(__NVRAM_FS_CMPT_SIMULATION__))
if (result < FS_NO_ERROR)
{
nvram_fat_last_err = result;
nvram_fat_last_line = __LINE__;
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]%s fail at %d\r\n",__FUNCTION__,__LINE__);
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]result = %d ,last_err=%d,last_line=%d\r\n",result,nvram_fat_last_err,nvram_fat_last_line);
MD_TRC_FUNC_NVRAM_DRV_FAT_THROW_EXCEPTION(nvram_fat_last_err, nvram_fat_last_line);
}
#else
if (nvram_param.opid_map != nvram_param.ret[0])
{
nvram_fat_last_err = nvram_param.ret[1] || result;
nvram_fat_last_line = __LINE__;
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]%s fail at %d\r\n",__FUNCTION__,__LINE__);
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]result = %d last_err=%d,last_line=%d\r\n",result,nvram_fat_last_err,nvram_fat_last_line);
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]nvram_param.opid_map(%d) != nvram_param.ret[0](%d)\r\n",nvram_param.opid_map,nvram_param.ret[0]);
MD_TRC_FUNC_NVRAM_DRV_FAT_THROW_EXCEPTION(nvram_fat_last_err, nvram_fat_last_line);
}
#endif
return result;
}
/*****************************************************************************
* FUNCTION
* nvram_read_exception_item
* DESCRIPTION
* read exception record from FAT.
* PARAMETERS
* buffer [?]
* nvramname [?]
* section_number [IN]
* size [IN]
* readsize [IN]
* RETURNS
* void
*****************************************************************************/
nvram_drv_status_enum nvram_drv_fat_read_exception_item(kal_uint8 *buffer,
kal_char *nvramname,
kal_uint16 section_number,
kal_uint32 size,
kal_uint32 readsize)
{
/*----------------------------------------------------------------*/
/* Local Variables */
/*----------------------------------------------------------------*/
kal_wchar filename[NVRAM_MAX_PATH_LEN];
FS_HANDLE hFile = 0;
kal_uint32 len = 0;
kal_int32 Ret;
kal_uint32 nvram_chksum_size = 0;
kal_char cfilename[NVRAM_FILE_LEN + 1] = {0};
kal_wchar wcfilename[NVRAM_FILE_LEN + 1] = {0};
nvram_ltable_entry_struct *ldi = NULL;
nvram_lid_chksum_info lid_chksum_info = {0};
/*----------------------------------------------------------------*/
/* Code Body */
/*----------------------------------------------------------------*/
if (section_number < 1)
{
/* kal_print("Nvram write: section_number < 1 !"); */
return NVRAM_DRV_INVALID_RECORD_ID;
}
/* translate record id to filename */
nvram_query_file_name(NVRAM_NVD_DATA, nvramname, filename);
nvram_query_file_name_by_path((kal_wchar *)filename, wcfilename);
kal_dchar2char((WCHAR *)wcfilename, cfilename);
nvram_util_get_data_item_by_fileprefix(&ldi, cfilename);
nvram_get_lid_chksum_algo_info(ldi, &lid_chksum_info, KAL_FALSE, KAL_FALSE);
nvram_chksum_size = lid_chksum_info.algo_info.chksum_algo_length;
/* open NV_RCD.(RCD#) file */
NVRAM_FS_START_EX(FS_OP_OPEN,filename);
hFile = FS_Open((const kal_wchar*)filename, FS_READ_ONLY | FS_OPEN_NO_DIR);
NVRAM_FS_END(FS_OP_OPEN,hFile);
if (hFile == FS_FILE_NOT_FOUND)
{
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]%s ->FS_Open %s fail \r\n",__FUNCTION__,nvramname);
return NVRAM_DRV_EMPTY_RECORD;
}
else if (hFile <= FS_NO_ERROR)
{
/* kal_print("Nvram read: FS_Open return error!"); */
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]%s ->FS_Open %s fail \r\n",__FUNCTION__,nvramname);
return NVRAM_DRV_FATAL_ERROR;
}
/* check if a empty record */
NVRAM_FS_START(FS_OP_GETFILESIZE);
Ret = FS_GetFileSize(hFile, &len);
NVRAM_FS_END(FS_OP_GETFILESIZE,Ret);
if ((Ret == FS_NO_ERROR) && (len == 0))
{
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]%s ->FS_GetFileSize fail,result=%d \r\n",__FUNCTION__,Ret);
NVRAM_FS_START(FS_OP_CLOSE);
Ret = FS_Close(hFile);
NVRAM_FS_END(FS_OP_CLOSE,Ret);
return NVRAM_DRV_EMPTY_RECORD;
}
/* seek to the record start */
NVRAM_FS_START(FS_OP_SEEK);
Ret = FS_Seek(hFile, (NVRAM_LDI_HEADER_SIZE + ((section_number - 1) * (size + nvram_chksum_size))), FS_FILE_BEGIN);
NVRAM_FS_END(FS_OP_SEEK,Ret);
if (Ret >= FS_NO_ERROR)
{
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]%s ->FS_Seek fail,result=%d \r\n",__FUNCTION__,Ret);
NVRAM_FS_START(FS_OP_READ);
Ret = FS_Read(hFile, buffer, (kal_uint32) readsize, &len);
NVRAM_FS_END(FS_OP_READ,Ret);
}
if (Ret != FS_NO_ERROR)
{
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]%s ->FS_Read fail,result=%d \r\n",__FUNCTION__,Ret);
/* kal_print("Nvram read: Read error!"); */
NVRAM_FS_START(FS_OP_CLOSE);
Ret = FS_Close(hFile);
NVRAM_FS_END(FS_OP_CLOSE,Ret);
return NVRAM_DRV_CHECKSUM_ERROR;
}
NVRAM_FS_START(FS_OP_CLOSE);
Ret = FS_Close(hFile);
NVRAM_FS_END(FS_OP_CLOSE,Ret);
return NVRAM_DRV_OK;
}
/*****************************************************************************
* FUNCTION
* nvram_drv_fat_prepare_data
* DESCRIPTION
* copy data into buffer
* PARAMETERS
* source: [IN] source data
* offset: [IN] offset in data
* buffer: [OUT] buffer
* buffer_size: [IN] size of buffer
* RETURNS
* void
*****************************************************************************/
void nvram_drv_fat_prepare_data(kal_uint8 *buffer, const kal_uint8 *source, kal_uint32 offset, kal_uint32 buffer_size)
{
/*----------------------------------------------------------------*/
/* Local Variables */
/*----------------------------------------------------------------*/
/*----------------------------------------------------------------*/
/* Code Body */
/*----------------------------------------------------------------*/
if (source == NVRAM_EF_ZERO_DEFAULT)
{
nvram_memset(buffer, 0x00, buffer_size);
}
else if (source == NVRAM_EF_FF_DEFAULT)
{
nvram_memset(buffer, 0xFF, buffer_size);
}
else
{
kal_mem_cpy(buffer, source+offset, buffer_size);
}
}
#ifdef __NVRAM_WRITE_WITH_FILE_SIZE__
/*****************************************************************************
* FUNCTION
* nvram_drv_fat_write_multiple
* DESCRIPTION
* write record(s) to FAT.
* PARAMETERS
* hFile [?]
* buffer [?]
* rec_amount [IN]
* rec_size [IN]
* RETURNS
* void
*****************************************************************************/
kal_int32 nvram_drv_fat_write_multiple(
FS_HANDLE hFile,
const kal_uint8 *buffer,
kal_uint16 rec_index,
kal_uint16 rec_amount,
kal_uint32 rec_size,
nvram_ltable_entry_struct *ldi)
{
/*----------------------------------------------------------------*/
/* Local Variables */
/*----------------------------------------------------------------*/
kal_uint32 len = 0, remainLen = 0;
kal_uint8 *chksum = NULL;
kal_uint32 max_rec_amount;
kal_uint32 section_size;
kal_uint32 working_buffer_size;
kal_uint8 *working_buffer = NULL;
kal_int32 result = NVRAM_DRV_OK;
kal_uint32 i;
kal_uint32 rec_in_block;
kal_uint32 nvram_chksum_size = 0;
nvram_lid_chksum_info lid_chksum_info = {0};
#ifdef __NVRAM_LID_CACHE__
kal_uint32 cache_offset = 0;
kal_uint32 temp_cache_offset = 0;
kal_uint16 temp_rec_index = rec_index;
#endif
/*----------------------------------------------------------------*/
/* Code Body */
/*----------------------------------------------------------------*/
nvram_get_lid_chksum_algo_info(ldi, &lid_chksum_info, KAL_FALSE, KAL_FALSE);
nvram_chksum_size = lid_chksum_info.algo_info.chksum_algo_length;
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP, "[NVUT_UTIL_CAL]%s():%d NVRAM chksize %d \n\r", __FUNCTION__, __LINE__,nvram_chksum_size);
#ifdef __NVRAM_BIND_TO_CHIP_CIPHER__
if ((ldi->attr & NVRAM_ATTR_MSP)||(ldi->attr & NVRAM_ATTR_CONFIDENTIAL))
{
/* 16 byte alignment */
remainLen = NVRAM_MSP_ALIGNMENT_REMAINDER(rec_size + nvram_chksum_size);
}
#else
if (ldi->attr & NVRAM_ATTR_CONFIDENTIAL)
{
/* 16 byte alignment */
remainLen = NVRAM_MSP_ALIGNMENT_REMAINDER(rec_size + nvram_chksum_size);
}
#endif
//16bytes alignment, limitation: msp data will be oversize
section_size = rec_size + nvram_chksum_size + remainLen;
working_buffer_size = section_size * rec_amount;
if (rec_index > 1)
{
NVRAM_FS_START(FS_OP_SEEK);
result = FS_Seek(hFile, (rec_index - 1) * section_size, FS_FILE_CURRENT);
NVRAM_FS_END(FS_OP_SEEK,result);
if (FS_NO_ERROR > result)
{
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]%s ->FS_Seek fail,result=%d\r\n",__FUNCTION__,result);
nvram_fat_last_line = __LINE__;
goto final;
}
}
if (working_buffer_size > MAX_NVRAM_RECORD_SIZE)
{
working_buffer_size = MAX_NVRAM_RECORD_SIZE;
}
working_buffer = (kal_uint8*) get_ctrl_buffer(working_buffer_size);
max_rec_amount = working_buffer_size/section_size;
chksum = (kal_uint8*) get_ctrl_buffer(nvram_chksum_size);
#ifdef __NVRAM_LID_CACHE__
cache_offset = 0;
if((!NVRAM_IS_ATTR_RAW_DATA(ldi->attr)) && NVRAM_WR_2_FILE_WITH_2_CACHE(ldi->LID))
{
if(NVRAM_IO_ERRNO_OK !=(result = get_lid_record_cache_offset(ldi, rec_index, section_size, &cache_offset)))
{
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]%s ->get_lid_record_cache_offset fail,result=%d\r\n",__FUNCTION__,result);
result = NVRAM_DRV_INVALID_RECORD_ID;
nvram_fat_last_line = __LINE__;
goto final;
}
}
temp_cache_offset = cache_offset;
#endif
if (!(ldi->attr & NVRAM_ATTR_MSP) && !(ldi->attr & NVRAM_ATTR_CONFIDENTIAL) &&
buffer != NVRAM_EF_ZERO_DEFAULT && buffer != NVRAM_EF_FF_DEFAULT)
{
for(i = 0; i < rec_amount; i++)
{
if (ldi->attr & NVRAM_ATTR_MULTI_DEFAULT)
{
//rec_index start from 1
kal_mem_set(chksum, 0, nvram_chksum_size);
nvram_util_caculate_checksum(ldi, buffer + (i+rec_index-1)*rec_size, rec_size,chksum);
kal_mem_cpy(working_buffer + i*(rec_size + nvram_chksum_size), buffer + (i+rec_index-1)*rec_size, rec_size);
kal_mem_cpy(working_buffer + i*(rec_size + nvram_chksum_size)+rec_size, chksum, nvram_chksum_size);
}
else
{
if (i==0)
{
kal_mem_set(chksum, 0, nvram_chksum_size);
nvram_util_caculate_checksum(ldi, buffer, rec_size,chksum);
}
kal_mem_cpy(working_buffer + i*(rec_size + nvram_chksum_size), buffer, rec_size);
kal_mem_cpy(working_buffer + i*(rec_size + nvram_chksum_size)+rec_size, chksum, nvram_chksum_size);
}
//record integrated checksum
if((ldi->attr & NVRAM_ATTR_CHKSUM_INTEGRATE) && ldi->append_buffer) {
kal_mem_cpy((void *)(ldi->append_buffer + (i* nvram_chksum_size)), (void *)chksum, nvram_chksum_size);
}
if (i == (rec_amount - 1))
{
NVRAM_FS_START(FS_OP_WRITE);
result = FS_Write(hFile, working_buffer, section_size * rec_amount, &len);
NVRAM_FS_END(FS_OP_WRITE,result);
if (FS_NO_ERROR > result)
{
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]%s ->FS_Write fail,result=%d\r\n",__FUNCTION__,result);
nvram_fat_last_line = __LINE__;
goto final;
}
#ifdef __NVRAM_LID_CACHE__
if((!NVRAM_IS_ATTR_RAW_DATA(ldi->attr)) && NVRAM_WR_2_FILE_WITH_2_CACHE(ldi->LID))
{
nvram_write_data_to_cache(ldi, working_buffer, section_size * rec_amount, cache_offset);
mask_valid_bit_by_ltable_entry(ldi, rec_index, rec_amount);
}
#endif
}
}
goto final;
}
rec_in_block = 0;
max_rec_amount = working_buffer_size / section_size;
for (i = 0; i < rec_amount; i ++)
{
nvram_drv_fat_prepare_data(working_buffer + rec_in_block * section_size, buffer, (i+rec_index-1) * rec_size, rec_size);
kal_mem_set(chksum, 0, nvram_chksum_size);
nvram_util_caculate_checksum(ldi, working_buffer + rec_in_block * section_size, rec_size, chksum);
kal_mem_cpy(working_buffer + rec_in_block * section_size + rec_size, chksum, nvram_chksum_size);
//record integrated checksum
if((ldi->attr & NVRAM_ATTR_CHKSUM_INTEGRATE) && ldi->append_buffer) {
kal_mem_cpy((void *)(ldi->append_buffer + (i* nvram_chksum_size)), (void *)chksum, nvram_chksum_size);
}
if (remainLen)
{
kal_mem_set(working_buffer + rec_in_block * section_size + rec_size + nvram_chksum_size , 0x00, remainLen);
}
if (ldi->attr & NVRAM_ATTR_CONFIDENTIAL)
{
//custom_nvram_encrypt(nvram_ptr->secret_key, working_buffer + rec_in_block * section_size, rec_size, rec_size);
nvram_AES_encrypt(working_buffer + rec_in_block * section_size, section_size);
}
#ifdef __NVRAM_BIND_TO_CHIP_CIPHER__
if (ldi->attr & NVRAM_ATTR_MSP)
{
/* this solution is only for work arround */
#if (defined(__SMART_PHONE_MODEM__) || defined(__CCCIFS_SUPPORT__))
kal_uint8 *working_buffer2 = (kal_uint8*) get_ctrl_buffer(section_size);
kal_uint8 *working_buffer3 = (kal_uint8*) get_ctrl_buffer(section_size);
//copy the original data from working_buffer to working_buffer2
memcpy(working_buffer2, working_buffer + rec_in_block * section_size, section_size);
do
{
nvram_trace_to_file(__LINE__, 999, 0, 0, 0, 0);
nvram_trace_to_file(nvram_ptr->secret_key[0], nvram_ptr->secret_key[1], nvram_ptr->secret_key[2], nvram_ptr->secret_key[3], 0, 0);
nvram_trace_to_file(working_buffer[rec_in_block*section_size], working_buffer[rec_in_block*section_size + 1], working_buffer[rec_in_block*section_size + 2], working_buffer[rec_in_block*section_size + 3], 0, 0);
//encrypt working_buffer
SST_Secure_Algo(NVRAM_MSP_ENCRYPT, (kal_uint32)working_buffer + rec_in_block * section_size, section_size, nvram_ptr->secret_key, working_buffer + rec_in_block * section_size);
nvram_trace_to_file(working_buffer[rec_in_block*section_size], working_buffer[rec_in_block*section_size + 1], working_buffer[rec_in_block*section_size + 2], working_buffer[rec_in_block*section_size + 3], 0, 0);
//copy the encrypted data from working_buffer to working_buffer3
memcpy(working_buffer3, working_buffer + rec_in_block * section_size, section_size);
//decrypt the working_buffer3
SST_Secure_Algo(NVRAM_MSP_DECRYPT, (kal_uint32)working_buffer3, section_size, nvram_ptr->secret_key, working_buffer3);
//compare the data between the working_buffer2 & working_buffer3
if (memcmp(working_buffer2, working_buffer3, section_size) == 0)
{
//encrypt PASS
break;
}
else
{
//encrypt FAIL, try again, WTF
memcpy(working_buffer + rec_in_block * section_size, working_buffer2, section_size);
}
}while(1);
free_ctrl_buffer(working_buffer2);
free_ctrl_buffer(working_buffer3);
working_buffer2 = NULL;
working_buffer3 = NULL;
#else
SST_Secure_Algo(NVRAM_MSP_ENCRYPT, (kal_uint32)working_buffer + rec_in_block * section_size, section_size, nvram_ptr->secret_key, working_buffer + rec_in_block * section_size);
#endif
}
#endif
/* if this is not multi default, no need to prepare data anymore */
if (!(ldi->attr & NVRAM_ATTR_MULTI_DEFAULT))
{
break;
}
rec_in_block ++;
if (rec_in_block == max_rec_amount || i == rec_amount - 1)
{
NVRAM_FS_START(FS_OP_WRITE);
result = FS_Write(hFile, working_buffer, section_size * rec_in_block, &len);
NVRAM_FS_END(FS_OP_WRITE,result);
if (FS_NO_ERROR > result)
{
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]%s ->FS_Write fail,result=%d\r\n",__FUNCTION__,result);
nvram_fat_last_line = __LINE__;
goto final;
}
#ifdef __NVRAM_LID_CACHE__
if((!NVRAM_IS_ATTR_RAW_DATA(ldi->attr)) && NVRAM_WR_2_FILE_WITH_2_CACHE(ldi->LID))
{
nvram_write_data_to_cache(ldi, working_buffer, section_size * rec_in_block, temp_cache_offset);
mask_valid_bit_by_ltable_entry(ldi, temp_rec_index, rec_in_block);
temp_cache_offset += section_size * rec_in_block;
temp_rec_index += rec_in_block;
}
#endif
rec_in_block = 0;
}
}
/* special handling for not multi default */
if (!(ldi->attr & NVRAM_ATTR_MULTI_DEFAULT))
{
for (i = 0; i < rec_amount; i++)
{
//record integrated checksum
if((ldi->attr & NVRAM_ATTR_CHKSUM_INTEGRATE) && ldi->append_buffer)
{
kal_mem_cpy((void *)(ldi->append_buffer + (i* nvram_chksum_size)), (void *)(working_buffer+rec_size), nvram_chksum_size);
}
NVRAM_FS_START(FS_OP_WRITE);
result = FS_Write(hFile, working_buffer, section_size, &len);
NVRAM_FS_END(FS_OP_WRITE,result);
if (FS_NO_ERROR > result)
{
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]%s ->FS_Write fail,result=%d\r\n",__FUNCTION__,result);
nvram_fat_last_line = __LINE__;
goto final;
}
#ifdef __NVRAM_LID_CACHE__
temp_cache_offset = cache_offset + section_size * i;
if((!NVRAM_IS_ATTR_RAW_DATA(ldi->attr)) && NVRAM_WR_2_FILE_WITH_2_CACHE(ldi->LID))
{
nvram_write_data_to_cache(ldi, working_buffer, section_size, temp_cache_offset);
mask_valid_bit_by_ltable_entry(ldi, rec_index+i, 1);
}
#endif
}
}
final:
if (working_buffer)
{
free_ctrl_buffer(working_buffer);
working_buffer = NULL;
}
if (chksum)
{
free_ctrl_buffer(chksum);
chksum = NULL;
}
if (FS_NO_ERROR > result)
{
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]%s fail at %d,result=%d\r\n",__FUNCTION__,__LINE__,result);
nvram_fat_last_err = result;
MD_TRC_FUNC_NVRAM_DRV_FAT_THROW_EXCEPTION(nvram_fat_last_err, nvram_fat_last_line);
return result;
}
return NVRAM_DRV_OK;
}
#endif
/*****************************************************************************
* FUNCTION
* nvram_drv_fat_write_section
* DESCRIPTION
* write record(s) to FAT.
* PARAMETERS
* buffer [?]
* nvramname [?]
* section_number [IN]
* size [IN]
* initialize [IN] true for reset, false for normal write.
* RETURNS
* void
*****************************************************************************/
kal_int32 nvram_drv_fat_write_section(
FS_HANDLE hFile,
const kal_uint8 *buffer,
kal_uint16 rec_index,
kal_uint16 rec_amount,
kal_uint32 rec_size,
nvram_ltable_entry_struct *ldi,
kal_uint32 filesize)
{
/*----------------------------------------------------------------*/
/* Local Variables */
/*----------------------------------------------------------------*/
kal_uint32 len = 0, remainLen = 0;
kal_uint8 *chksum = NULL;
kal_uint32 max_rec_amount;
kal_uint32 section_size;
kal_uint32 working_buffer_size;
kal_uint8 *working_buffer = NULL;
kal_int32 result = NVRAM_DRV_OK;
kal_bool encrypt_data = KAL_FALSE;
kal_uint32 i;
kal_uint32 nvram_chksum_size = 0;
nvram_lid_chksum_info lid_chksum_info = {0};
#ifdef __NVRAM_LID_CACHE__
kal_uint32 cache_offset = 0;
kal_uint32 temp_cache_offset = 0;
kal_uint16 temp_rec_index = rec_index;
#endif
/*----------------------------------------------------------------*/
/* Code Body */
/*----------------------------------------------------------------*/
nvram_get_lid_chksum_algo_info(ldi, &lid_chksum_info, KAL_FALSE, KAL_FALSE);
nvram_chksum_size = lid_chksum_info.algo_info.chksum_algo_length;
#ifdef __NVRAM_BIND_TO_CHIP_CIPHER__
if ((ldi->attr & NVRAM_ATTR_MSP)||(ldi->attr & NVRAM_ATTR_CONFIDENTIAL))
{
/* 16 byte alignment */
remainLen = NVRAM_MSP_ALIGNMENT_REMAINDER(rec_size + nvram_chksum_size);
encrypt_data = KAL_TRUE;
}
#else
if (ldi->attr & NVRAM_ATTR_CONFIDENTIAL)
{
/* 16 byte alignment */
remainLen = NVRAM_MSP_ALIGNMENT_REMAINDER(rec_size + nvram_chksum_size);
encrypt_data = KAL_TRUE;
}
#endif
section_size = rec_size + nvram_chksum_size + remainLen;
working_buffer_size = section_size * rec_amount;
if (working_buffer_size > MAX_NVRAM_RECORD_SIZE)
{
working_buffer_size = MAX_NVRAM_RECORD_SIZE;
}
working_buffer = (kal_uint8*) get_ctrl_buffer(working_buffer_size);
chksum = (kal_uint8*) get_ctrl_buffer(nvram_chksum_size);
if (rec_index > 1 && rec_amount == 1)
{
NVRAM_FS_START(FS_OP_SEEK);
result = FS_Seek(hFile, (rec_index - 1) * section_size, FS_FILE_CURRENT);
NVRAM_FS_END(FS_OP_SEEK,result);
if (FS_NO_ERROR > result)
{
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]%s ->FS_Seek fail at %d,result=%d\r\n",__FUNCTION__,__LINE__,result);
nvram_fat_last_line = __LINE__;
goto final;
}
}
/* we can write data into FS directly, we don't need another buffer*/
if (!(ldi->attr & NVRAM_ATTR_MSP) && !(ldi->attr & NVRAM_ATTR_CONFIDENTIAL) &&
#if defined(__MTK_TARGET__) && defined(__NVRAM_IMPORTANT_PARTITIONS__)
!(ldi->attr & NVRAM_ATTR_COMMITTED) &&
#endif
buffer != NVRAM_EF_ZERO_DEFAULT && buffer != NVRAM_EF_FF_DEFAULT)
{
#ifdef __NVRAM_LID_CACHE__
cache_offset = 0;
if((!NVRAM_IS_ATTR_RAW_DATA(ldi->attr)) && NVRAM_WR_2_FILE_WITH_2_CACHE(ldi->LID))
{
if(NVRAM_IO_ERRNO_OK !=(result = get_lid_record_cache_offset(ldi, rec_index, section_size, &cache_offset)))
{
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]%s ->get_lid_record_cache_offset fail at %d,result=%d\r\n",__FUNCTION__,__LINE__,result);
result = NVRAM_DRV_INVALID_RECORD_ID;
nvram_fat_last_line = __LINE__;
goto final;
}
}
#endif
for(i = 0;i < rec_amount;i++)
{
nvram_memset(working_buffer, (kal_uint8) NVRAM_EF_ZERO_DEFAULT_VALUE, working_buffer_size);
if ((i == 0 || (ldi->attr & NVRAM_ATTR_MULTI_DEFAULT)) &&
!NVRAM_IS_ATTR_RAW_DATA(ldi->attr) )
{
kal_mem_set(chksum, 0, nvram_chksum_size);
nvram_util_caculate_checksum(ldi, buffer + i * rec_size, rec_size, chksum);
}
if (ldi->attr & NVRAM_ATTR_MULTI_DEFAULT)
{
if (NVRAM_IS_ATTR_RAW_DATA(ldi->attr))
{
NVRAM_FS_START(FS_OP_WRITE);
result = FS_Write(hFile, (void *)(buffer + i * rec_size), rec_size, &len);
NVRAM_FS_END(FS_OP_WRITE,result);
if (FS_NO_ERROR > result)
{
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]%s ->FS_Write fail at %d,result=%d\r\n",__FUNCTION__,__LINE__,result);
nvram_fat_last_line = __LINE__;
goto final;
}
}
else
{
kal_mem_cpy(working_buffer, (void *)(buffer + i * rec_size), rec_size);
}
}
else
{
if (NVRAM_IS_ATTR_RAW_DATA(ldi->attr))
{
NVRAM_FS_START(FS_OP_WRITE);
result = FS_Write(hFile, (void *)buffer, rec_size, &len);
NVRAM_FS_END(FS_OP_WRITE,result);
if (FS_NO_ERROR > result)
{
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]%s ->FS_Write fail at %d,result=%d\r\n",__FUNCTION__,__LINE__,result);
nvram_fat_last_line = __LINE__;
goto final;
}
}
else
{
kal_mem_cpy(working_buffer, (void *)buffer, rec_size);
}
}
if (NVRAM_IS_ATTR_RAW_DATA(ldi->attr)) {
goto final;
}
//write data & checksum
kal_mem_cpy((void *)(working_buffer + rec_size), (void *)chksum, nvram_chksum_size);
NVRAM_FS_START(FS_OP_WRITE);
result = FS_Write(hFile, working_buffer, section_size, &len);
NVRAM_FS_END(FS_OP_WRITE,result);
if (FS_NO_ERROR > result)
{
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]%s ->FS_Write fail at %d,result=%d\r\n",__FUNCTION__,__LINE__,result);
nvram_fat_last_line = __LINE__;
goto final;
}
#ifdef __NVRAM_LID_CACHE__
if(NVRAM_WR_2_FILE_WITH_2_CACHE(ldi->LID))
{
nvram_write_data_to_cache(ldi, working_buffer, section_size, (cache_offset + i * section_size));
mask_valid_bit_by_ltable_entry(ldi, rec_index + i, 1);
}
#endif
//record integrated checksum
if((ldi->attr & NVRAM_ATTR_CHKSUM_INTEGRATE) && ldi->append_buffer) {
kal_mem_cpy((void *)(ldi->append_buffer + (i* nvram_chksum_size)), (void *)chksum, nvram_chksum_size);
}
}
goto final;
}
//working_buffer_size = MAX_NVRAM_RECORD_SIZE;
//MAX_NVRAM_RECORD_SIZE = (NVRAM_CUSTOM_CFG_MAX_RECORD_SECTOR_NUM * NVRAM_RECORD_SECTOR_SIZE)
// = (16 or 4) * 512
#ifdef __NVRAM_LARGE_RECORD_SIZE__
/* size too large , we need to operate block by block */
if (section_size > working_buffer_size)
{
/* we need to prepare extra working buffer;
and due to msp need 16-bytes alignment, therefore
we set the working buffer to 16-bytes alignment also */
kal_uint8 *tmpchksum = NULL;
kal_int32 j,cs_idx;
working_buffer_size = NVRAM_MSP_ALIGNMENT_FLOOR(working_buffer_size) - NVRAM_MSP_ALIGNMENT;
tmpchksum = (kal_uint8*) get_ctrl_buffer(nvram_chksum_size);
#ifdef __NVRAM_LID_CACHE__
cache_offset = 0;
temp_cache_offset = 0;
if((!NVRAM_IS_ATTR_RAW_DATA(ldi->attr)) && NVRAM_WR_2_FILE_WITH_2_CACHE(ldi->LID))
{
if(NVRAM_IO_ERRNO_OK !=(result = get_lid_record_cache_offset(ldi, rec_index, section_size, &cache_offset)))
{
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]%s ->get_lid_record_cache_offset fail at %d,result=%d\r\n",__FUNCTION__,__LINE__,result);
result = NVRAM_DRV_INVALID_RECORD_ID;
nvram_fat_last_line = __LINE__;
if (tmpchksum)
{
free_ctrl_buffer(tmpchksum);
tmpchksum = NULL;
}
goto final;
}
}
#endif
for (i = 0 ; i < rec_amount; i++)
{
#ifdef __NVRAM_LID_CACHE__
temp_cache_offset = cache_offset + i*section_size;
#endif
for (j = 0; j < rec_size; j += working_buffer_size)
{
kal_int32 byte_in_block = rec_size - j;
kal_bool last_block = KAL_FALSE;
if (byte_in_block > working_buffer_size)
{
byte_in_block = working_buffer_size;
if (!(ldi->attr & NVRAM_ATTR_MULTI_DEFAULT))
{
nvram_drv_fat_prepare_data(working_buffer, buffer, j, byte_in_block);
}
else
{
nvram_drv_fat_prepare_data(working_buffer, buffer, i * rec_size + j, byte_in_block);
}
}
else /* last block */
{
if (!(ldi->attr & NVRAM_ATTR_MULTI_DEFAULT))
{
nvram_drv_fat_prepare_data(working_buffer, buffer, j, byte_in_block);
}
else
{
nvram_drv_fat_prepare_data(working_buffer, buffer, i * rec_size + j, byte_in_block);
}
last_block = KAL_TRUE;
}
if (i == 0 || ldi->attr & NVRAM_ATTR_MULTI_DEFAULT)
{
if (j == 0)
{
kal_mem_set(chksum, 0, nvram_chksum_size);
}
kal_mem_set(tmpchksum, 0, nvram_chksum_size);
nvram_util_caculate_checksum(ldi, working_buffer, byte_in_block, tmpchksum);
for(cs_idx= 0; cs_idx < nvram_chksum_size;cs_idx++){
chksum[cs_idx] += tmpchksum[cs_idx];
}
}
/* last block */
if (last_block)
{
kal_mem_cpy(working_buffer + byte_in_block, chksum, nvram_chksum_size);
kal_mem_set(working_buffer + byte_in_block + nvram_chksum_size, 0, remainLen);
byte_in_block += (nvram_chksum_size + remainLen);
}
if (ldi->attr & NVRAM_ATTR_CONFIDENTIAL)
{
//custom_nvram_encrypt(nvram_ptr->secret_key, working_buffer, byte_in_block, rec_size);
nvram_AES_encrypt(working_buffer, byte_in_block);
}
#ifdef __NVRAM_BIND_TO_CHIP_CIPHER__
if (ldi->attr & NVRAM_ATTR_MSP)
{
SST_Secure_Algo(NVRAM_MSP_ENCRYPT, (kal_uint32)working_buffer, byte_in_block, nvram_ptr->secret_key, working_buffer);
}
#endif
NVRAM_FS_START(FS_OP_WRITE);
result = FS_Write(hFile, working_buffer, byte_in_block, &len);
NVRAM_FS_END(FS_OP_WRITE,result);
if (FS_NO_ERROR > result)
{
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]%s ->FS_Write fail at %d,result=%d\r\n",__FUNCTION__,__LINE__,result);
nvram_fat_last_line = __LINE__;
if (tmpchksum)
{
free_ctrl_buffer(tmpchksum);
tmpchksum = NULL;
}
goto final;
}
#ifdef __NVRAM_LID_CACHE__
if((!NVRAM_IS_ATTR_RAW_DATA(ldi->attr)) && NVRAM_WR_2_FILE_WITH_2_CACHE(ldi->LID))
{
nvram_write_data_to_cache(ldi, working_buffer, byte_in_block, temp_cache_offset);
temp_cache_offset = temp_cache_offset + byte_in_block;
}
#endif
}
#ifdef __NVRAM_LID_CACHE__
if((!NVRAM_IS_ATTR_RAW_DATA(ldi->attr)) && NVRAM_WR_2_FILE_WITH_2_CACHE(ldi->LID))
{
mask_valid_bit_by_ltable_entry(ldi, rec_index + i, 1);
}
#endif
//record integrated checksum
if((ldi->attr & NVRAM_ATTR_CHKSUM_INTEGRATE) && ldi->append_buffer) {
kal_mem_cpy((void *)(ldi->append_buffer + (i* nvram_chksum_size)), (void *)chksum, nvram_chksum_size);
}
}
if (tmpchksum)
{
free_ctrl_buffer(tmpchksum);
tmpchksum = NULL;
}
}
else
#endif
{
kal_uint32 rec_in_block = 0;
max_rec_amount = working_buffer_size / section_size;
#ifdef __NVRAM_LID_CACHE__
cache_offset = 0;
temp_cache_offset = 0;
temp_rec_index = rec_index;
if((!NVRAM_IS_ATTR_RAW_DATA(ldi->attr)) && NVRAM_WR_2_FILE_WITH_2_CACHE(ldi->LID))
{
if(NVRAM_IO_ERRNO_OK !=(result = get_lid_record_cache_offset(ldi, rec_index, section_size, &cache_offset)))
{
result = NVRAM_DRV_INVALID_RECORD_ID;
nvram_fat_last_line = __LINE__;
goto final;
}
}
#endif
for (i = 0; i < rec_amount ; i ++)
{
/*
* Write several record at once to reduce io Write
* case a: all remain record
* section_number - i
* case b: max record we can write in one time
* max_rec_amount
* check which case is smaller
*/
nvram_drv_fat_prepare_data(working_buffer + rec_in_block * section_size, buffer, i * rec_size, rec_size);
kal_mem_set(chksum, 0, nvram_chksum_size);
nvram_util_caculate_checksum(ldi, working_buffer + rec_in_block * section_size, rec_size, chksum);
kal_mem_cpy(working_buffer + rec_in_block * section_size + rec_size, chksum, nvram_chksum_size);
if (remainLen)
{
kal_mem_set(working_buffer + rec_in_block * section_size + rec_size + nvram_chksum_size , 0x00, remainLen);
}
if (ldi->attr & NVRAM_ATTR_CONFIDENTIAL)
{
#ifdef __NVRAM_CRYPT_TEST__
if (bWriteMsp == 1){
kal_mem_cpy(&NVRAM_EF_MSP_TEST_W,working_buffer,NVRAM_MSP_TEST_LEN);
}
#endif
nvram_AES_encrypt(working_buffer + rec_in_block * section_size, section_size);
#ifdef __NVRAM_CRYPT_TEST__
if (bWriteMsp == 1){
kal_mem_cpy(&NVRAM_EF_MSP_TEST_W[NVRAM_MSP_TEST_LEN],working_buffer,NVRAM_MSP_TEST_LEN);
}
#endif
}
#ifdef __NVRAM_BIND_TO_CHIP_CIPHER__
if (ldi->attr & NVRAM_ATTR_MSP)
{
SST_Secure_Algo(NVRAM_MSP_ENCRYPT, (kal_uint32)working_buffer + rec_in_block * section_size, section_size, nvram_ptr->secret_key, working_buffer + rec_in_block * section_size);
}
#endif
//record integrated checksum
if((ldi->attr & NVRAM_ATTR_CHKSUM_INTEGRATE) && ldi->append_buffer) {
kal_mem_cpy((void *)(ldi->append_buffer + (i* nvram_chksum_size)), (void *)chksum, nvram_chksum_size);
}
/* if this is not multi default, no need to prepare data anymore */
if (!(ldi->attr & NVRAM_ATTR_MULTI_DEFAULT))
{
break;
}
rec_in_block ++;
if (rec_in_block == max_rec_amount || i == rec_amount - 1)
{
NVRAM_FS_START(FS_OP_WRITE);
result = FS_Write(hFile, working_buffer, section_size * rec_in_block, &len);
NVRAM_FS_END(FS_OP_WRITE,result);
if (FS_NO_ERROR > result)
{
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]%s ->FS_Write fail at %d,result=%d\r\n",__FUNCTION__,__LINE__,result);
nvram_fat_last_line = __LINE__;
goto final;
}
#ifdef __NVRAM_LID_CACHE__
if((!NVRAM_IS_ATTR_RAW_DATA(ldi->attr)) && NVRAM_WR_2_FILE_WITH_2_CACHE(ldi->LID))
{
nvram_write_data_to_cache(ldi, working_buffer, section_size * rec_in_block, cache_offset);
mask_valid_bit_by_ltable_entry(ldi, temp_rec_index, rec_in_block);
cache_offset += section_size * rec_in_block;
temp_rec_index += rec_in_block;
}
#endif
rec_in_block = 0;
}
}
/* special handling for not multi default */
if (!(ldi->attr & NVRAM_ATTR_MULTI_DEFAULT))
{
/* special handling for NVRAM_EF_ZERO_DEFAULT write speed up*/
if((buffer == NVRAM_EF_ZERO_DEFAULT) &&
(filesize <= NVRAM_LDI_HEADER_SIZE) &&
!encrypt_data )
{
#ifdef __NVRAM_LID_CACHE__
temp_rec_index = rec_index;
if((!NVRAM_IS_ATTR_RAW_DATA(ldi->attr)) && NVRAM_WR_2_FILE_WITH_2_CACHE(ldi->LID))
{
get_lid_record_cache_offset(ldi, rec_index, section_size, &cache_offset);
}
#endif
for(i = 0; i < rec_amount; i++) {
NVRAM_FS_START(FS_OP_SEEK);
result = FS_Seek(hFile, rec_size, FS_FILE_CURRENT);
NVRAM_FS_END(FS_OP_SEEK,result);
if(FS_NO_ERROR > result)
{
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]%s ->FS_Seek fail at %d,result=%d\r\n",__FUNCTION__,__LINE__,result);
nvram_fat_last_line = __LINE__;
goto final;
}
NVRAM_FS_START(FS_OP_WRITE);
result = FS_Write(hFile, (working_buffer + rec_size), nvram_chksum_size, &len);
NVRAM_FS_END(FS_OP_WRITE,result);
if (FS_NO_ERROR > result)
{
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]%s ->FS_Write fail at %d,result=%d\r\n",__FUNCTION__,__LINE__,result);
nvram_fat_last_line = __LINE__;
goto final;
}
#ifdef __NVRAM_LID_CACHE__
if((!NVRAM_IS_ATTR_RAW_DATA(ldi->attr)) && NVRAM_WR_2_FILE_WITH_2_CACHE(ldi->LID))
{
temp_cache_offset = cache_offset + i* section_size;
nvram_write_data_to_cache(ldi, working_buffer, section_size, temp_cache_offset);
mask_valid_bit_by_ltable_entry(ldi, rec_index + i, 1);
}
#endif
//record integrated checksum
if((ldi->attr & NVRAM_ATTR_CHKSUM_INTEGRATE) && ldi->append_buffer) {
kal_mem_cpy((void *)(ldi->append_buffer + (i* nvram_chksum_size)), (void *)(working_buffer + rec_size), nvram_chksum_size);
}
}
goto final;
}
if (rec_amount > 1)
{
for (i = 1; i < max_rec_amount && i < rec_amount; i++)
{
kal_mem_cpy(working_buffer + section_size * i, working_buffer, section_size);
//record integrated checksum
if((ldi->attr & NVRAM_ATTR_CHKSUM_INTEGRATE) && ldi->append_buffer) {
kal_mem_cpy((void *)(ldi->append_buffer + (i* nvram_chksum_size)), (void *)(working_buffer+rec_size), nvram_chksum_size);
}
}
}
#ifdef __NVRAM_CRYPT_TEST__
if (bWriteMsp == 1)
{
kal_mem_cpy(&NVRAM_EF_MSP_TEST_W[NVRAM_MSP_TEST_LEN*2],working_buffer,NVRAM_MSP_TEST_LEN);
nvram_create_report_msp_file(KAL_TRUE);
}
#endif
#ifdef __NVRAM_LID_CACHE__
temp_rec_index = rec_index;
if((!NVRAM_IS_ATTR_RAW_DATA(ldi->attr)) && NVRAM_WR_2_FILE_WITH_2_CACHE(ldi->LID))
{
get_lid_record_cache_offset(ldi, rec_index, section_size, &cache_offset);
}
temp_cache_offset = cache_offset;
#endif
for (i = 0 ; i < rec_amount ; i += max_rec_amount)
{
rec_in_block = (rec_amount - i) > max_rec_amount ? max_rec_amount: (rec_amount - i);
NVRAM_FS_START(FS_OP_WRITE);
result = FS_Write(hFile, working_buffer, section_size * rec_in_block, &len);
NVRAM_FS_END(FS_OP_WRITE,result);
if (FS_NO_ERROR > result)
{
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]%s ->FS_Write fail at %d,result=%d\r\n",__FUNCTION__,__LINE__,result);
nvram_fat_last_line = __LINE__;
goto final;
}
#ifdef __NVRAM_LID_CACHE__
if((!NVRAM_IS_ATTR_RAW_DATA(ldi->attr)) && NVRAM_WR_2_FILE_WITH_2_CACHE(ldi->LID))
{
nvram_write_data_to_cache(ldi, working_buffer, section_size * rec_in_block, temp_cache_offset);
mask_valid_bit_by_ltable_entry(ldi, temp_rec_index, rec_in_block);
temp_rec_index = temp_rec_index + rec_in_block;
temp_cache_offset = cache_offset + section_size * rec_in_block;
}
#endif
}
}
}
final:
if (working_buffer)
{
free_ctrl_buffer(working_buffer);
}
if (chksum)
{
free_ctrl_buffer(chksum);
chksum = NULL;
}
if (FS_NO_ERROR > result)
{
nvram_fat_last_err = result;
MD_TRC_FUNC_NVRAM_DRV_FAT_THROW_EXCEPTION(nvram_fat_last_err, nvram_fat_last_line);
return result;
}
return NVRAM_DRV_OK;
}
#ifdef __NVRAM_WRITE_WITH_FILE_SIZE__
/*****************************************************************************
* FUNCTION
* nvram_drv_fat_write_multRec
* DESCRIPTION
* write record(s) to FAT,now it only used at initiation stage
* PARAMETERS
* buffer [?]
* nvramname [?]
* section_number [IN]
* size [IN]
* initialize [IN] true for reset, false for normal write.
* RETURNS
* void
*****************************************************************************/
nvram_drv_status_enum nvram_drv_fat_write_multRec(nvram_ltable_entry_struct *ldi,
kal_char *nvramname,
nvram_folder_enum nvram_folder,
kal_uint32 file_offset,
kal_uint16 rec_index,
kal_uint16 rec_amount,
kal_uint32 rec_size,
const kal_uint8 *buffer,
kal_bool initialize)
{
kal_int32 result = FS_NO_ERROR;
kal_int32 ret = FS_NO_ERROR;
#ifdef __NVRAM_LID_CACHE__
if(NVRAM_WR_WITH_CACHE(ldi->LID) && (!(NVRAM_IS_ATTR_RAW_DATA(ldi->attr))))
{
result = nvram_drv_fat_write_multiRec_to_cache(buffer, rec_index, rec_amount, rec_size, ldi);
}
else
#endif
{
/*----------------------------------------------------------------*/
/* Local Variables */
/*----------------------------------------------------------------*/
kal_wchar filename[NVRAM_MAX_PATH_LEN];
FS_HANDLE hFile = 0;
kal_uint32 openOption = FS_READ_WRITE | FS_OPEN_NO_DIR;
kal_uint32 len;
kal_uint32 nvram_chksum_size = 0;
nvram_lid_chksum_info lid_chksum_info = {0};
#if defined(__NVRAM_ACCESS_TIMEOUT_ASSERT__)
SGPT_CTRL_START_T start;
#endif
nvram_ldi_ota_header ota_header;
#ifdef __NVRAM_LID_CACHE__
kal_uint32 cache_offset = 0;
#endif
/*----------------------------------------------------------------*/
/* Code Body */
/*----------------------------------------------------------------*/
/* NVRAM GPT timeout assert start timer */
#if defined(__NVRAM_ACCESS_TIMEOUT_ASSERT__)
start.u2Tick= NVRAM_WRITE_GPT_TIMEOUT;
start.pfCallback=nvram_gpt_timeout_callback;
start.vPara=NULL;
#endif
nvram_util_take_mutex(g_nvram_fs_mutex);
nvram_get_lid_chksum_algo_info(ldi, &lid_chksum_info, KAL_FALSE, KAL_FALSE);
nvram_chksum_size = lid_chksum_info.algo_info.chksum_algo_length;
#if defined(__NVRAM_ACCESS_TIMEOUT_ASSERT__)
DclSGPT_Control(nvram_gpt_handle, SGPT_CMD_START, (DCL_CTRL_DATA_T*)&start); //start timer
#endif
do
{
if (rec_index < 1 || rec_amount < 1)
{
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]%s fail at %d\r\n",__FUNCTION__,__LINE__);
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]rec_index=%d,rec_amount=%d\r\n",rec_index,rec_amount);
nvram_fat_last_line = __LINE__;
result = NVRAM_DRV_INVALID_RECORD_ID;
break;
}
/* translate record id to filename */
nvram_query_file_name(nvram_folder, nvramname, filename);
/* set the attribute to empty before write data
sometime the files may be read only if the nvram lock is turn on
ex: software update when nvram lock is turned on
But it is not a good solution here, we should unlock it in io layer */
openOption |= FS_CREATE;
#if (defined(__SMART_PHONE_MODEM__) || defined(__CCCIFS_SUPPORT__)) && defined(__MTK_TARGET__)
if (ldi->attr & NVRAM_ATTR_COMMITTED)
{
openOption |= FS_COMMITTED;
}
#endif
//Get appdenix header info
if(ldi->attr & NVRAM_ATTR_CHKSUM_INTEGRATE) {
ldi->append_buffer = get_ctrl_buffer(rec_amount * nvram_chksum_size);
}
NVRAM_FS_START_EX(FS_OP_OPEN,filename);
hFile = FS_Open((const kal_wchar*)filename, openOption);
NVRAM_FS_END(FS_OP_OPEN,hFile);
if (hFile == FS_FILE_NOT_FOUND)
{
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]%s->FS_Open %s fail\r\n",__FUNCTION__,nvramname);
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]Fail at %d,FS_FILE_NOT_FOUND result=%d\r\n",__LINE__,hFile);
nvram_fat_last_line = __LINE__;
result = NVRAM_DRV_EMPTY_RECORD;
break;
}
else if (hFile <= FS_NO_ERROR)
{
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]%s->FS_Open %s fail\r\n",__FUNCTION__,nvramname);
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]Fail at %d,result=%d\r\n",__LINE__,hFile);
nvram_fat_last_line = __LINE__;
result = hFile;
break;
}
if (!nvram_util_has_file_created(ldi))
{
kal_uint32 ldi_hd_buffer_size = 0;
kal_uint8 ldi_hd_buffer[NVRAM_LDI_HEADER_SIZE] = {0};
//prepare header data and write header
nvram_prepare_data_header(ldi, ldi_hd_buffer);
NVRAM_FS_START(FS_OP_WRITE);
result = FS_Write(hFile, ldi_hd_buffer, NVRAM_LDI_HEADER_SIZE, &ldi_hd_buffer_size);
NVRAM_FS_END(FS_OP_WRITE,result);
if (result < FS_NO_ERROR)
{
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]%s->FS_Write fail at %d,result=%d\r\n",__FUNCTION__,__LINE__,result);
nvram_fat_last_line = __LINE__;
break;
}
#ifdef __NVRAM_LID_CACHE__
cache_offset = 0;
if((!NVRAM_IS_ATTR_RAW_DATA(ldi->attr)) && NVRAM_WR_2_FILE_WITH_2_CACHE(ldi->LID))
{
get_lid_cache_base_address(ldi, &cache_offset);
nvram_write_data_to_cache(ldi, (void *)ldi_hd_buffer, NVRAM_LDI_HEADER_SIZE, cache_offset);
mask_valid_bit_by_ltable_entry(ldi, 0, 1);
}
#endif
}
else
{
NVRAM_FS_START(FS_OP_SEEK);
result = FS_Seek(hFile, file_offset, FS_FILE_BEGIN);
NVRAM_FS_END(FS_OP_SEEK,result);
if (file_offset && FS_NO_ERROR > result)
{
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]%s->FS_Seek fail at %d,result=%d\r\n",__FUNCTION__,__LINE__,result);
nvram_fat_last_line = __LINE__;
break;
}
}
result = nvram_drv_fat_write_multiple(hFile, buffer, rec_index, rec_amount, rec_size, ldi);
}while(0);
//write-back appdenix header info
if(ldi->attr & NVRAM_ATTR_CHKSUM_INTEGRATE) {
//Write appendix header
kal_mem_set(&ota_header, 0, NVRAM_LDI_APPENDIX_HEADER_SIZE);
nvram_prepare_appendix_header(NVRAM_APPEND_TYPE_CHKSUM, (nvram_ldi_appendix_header*)(&ota_header), ldi, NVRAM_LDI_APPENDIX_HEADER_SIZE);
NVRAM_FS_START(FS_OP_SEEK);
result = FS_Seek(hFile, ldi->append_offset, FS_FILE_BEGIN);
NVRAM_FS_END(FS_OP_SEEK,result);
NVRAM_FS_START(FS_OP_WRITE);
result = FS_Write(hFile, &ota_header, NVRAM_LDI_APPENDIX_HEADER_SIZE, &len);
NVRAM_FS_END(FS_OP_WRITE,result);
if (result < FS_NO_ERROR) {
kal_prompt_trace(MOD_NVRAM, "NVRAM appendix header write fail:0x%x\n\r", result);
kal_prompt_trace(MOD_NVRAM, "category:0x%x, attr:0x%x\n\r", ldi->category, ldi->attr);
kal_prompt_trace(MOD_NVRAM, "fileprefix:%s, fileverno:%s\n\r", ldi->fileprefix, ldi->fileverno);
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"NVRAM appendix header write fail:0x%x\r\n", result);
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"LID 0x%04X,category:0x%08X, attr:0x%08X\r\n",ldi->LID, ldi->category, ldi->attr);
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"fileprefix:%s, fileverno:%s\r\n", ldi->fileprefix, ldi->fileverno);
if(NVRAM_IS_ATTR_FAULT_ASSERT(ldi->attr)) {
if(ldi->append_buffer) {
free_ctrl_buffer(ldi->append_buffer);
ldi->append_buffer = NULL;
}
NVRAM_FS_START(FS_OP_CLOSE);
result = FS_Close(hFile);
NVRAM_FS_END(FS_OP_CLOSE,result);
NVRAM_EXT_ASSERT(KAL_FALSE, (kal_uint32)hFile, NVRAM_LOC_WRITE_FILE_FAIL_4, ldi->LID, result);
}
}
#ifdef __NVRAM_LID_CACHE__
else
{
cache_offset = 0;
if((!NVRAM_IS_ATTR_RAW_DATA(ldi->attr)) && NVRAM_WR_2_FILE_WITH_2_CACHE(ldi->LID))
{
get_lid_cache_base_address(ldi, &cache_offset);
cache_offset = cache_offset + ldi->append_offset;
nvram_write_data_to_cache(ldi, (void *)&ota_header, NVRAM_LDI_APPENDIX_HEADER_SIZE, cache_offset);
}
}
#endif
//Write appendix info
if(ldi->append_offset == 0) {
kal_mem_set(&ota_header, 0, NVRAM_LDI_OTA_HEADER_SIZE);
#if defined(__NVRAM_LID_CACHE__) && (defined(__NVRAM_LID_PREREAD__) || defined(__NVRAM_CACHE_BYPASS_W_LIST__))
if(KAL_TRUE == nvram_cache_read_ota_header(filename, hFile, &ota_header, NVRAM_LDI_OTA_HEADER_SIZE) &&
(ota_header.ldi_attr & NVRAM_ATTR_CHKSUM_INTEGRATE) )
#else
if(KAL_TRUE == nvram_read_ota_header(hFile, &ota_header, NVRAM_LDI_OTA_HEADER_SIZE) &&
(ota_header.ldi_attr & NVRAM_ATTR_CHKSUM_INTEGRATE) )
#endif
{
ldi->append_offset = nvram_appendix_header_offset(ldi);
}
else {
ldi->append_offset = -1;
}
}
if(ldi->append_offset > 0) {
NVRAM_FS_START(FS_OP_SEEK);
ret = FS_Seek(hFile, (ldi->append_offset + NVRAM_LDI_APPENDIX_HEADER_SIZE + ((rec_index - 1) * nvram_chksum_size)), FS_FILE_BEGIN);
NVRAM_FS_END(FS_OP_SEEK,ret);
NVRAM_FS_START(FS_OP_WRITE);
ret = FS_Write(hFile, ldi->append_buffer, (rec_amount * nvram_chksum_size), &len);
NVRAM_FS_END(FS_OP_WRITE,ret);
#ifdef __NVRAM_LID_CACHE__
cache_offset = 0;
if((!NVRAM_IS_ATTR_RAW_DATA(ldi->attr)) && NVRAM_WR_2_FILE_WITH_2_CACHE(ldi->LID))
{
get_lid_cache_base_address(ldi, &cache_offset);
cache_offset = cache_offset + (ldi->append_offset + NVRAM_LDI_APPENDIX_HEADER_SIZE + ((rec_index - 1) * nvram_chksum_size));
nvram_write_data_to_cache(ldi, (kal_uint8*)ldi->append_buffer, (rec_amount * nvram_chksum_size), cache_offset);
}
#endif
}
if(ldi->append_buffer) {
free_ctrl_buffer(ldi->append_buffer);
ldi->append_buffer = NULL;
}
}
if (hFile > FS_NO_ERROR)
{
NVRAM_FS_START(FS_OP_CLOSE);
ret = FS_Close(hFile);
NVRAM_FS_END(FS_OP_CLOSE,ret);
}
#if defined(__NVRAM_ACCESS_TIMEOUT_ASSERT__)
DclSGPT_Control(nvram_gpt_handle, SGPT_CMD_STOP, (DCL_CTRL_DATA_T*)NULL); //stop timer
#endif
nvram_util_give_mutex(g_nvram_fs_mutex);
/* Set the attribute back to original attribute */
if (result < FS_NO_ERROR)
{
nvram_fat_last_err = result;
MD_TRC_FUNC_NVRAM_DRV_FAT_THROW_EXCEPTION(nvram_fat_last_err, nvram_fat_last_line);
}
}
return result;
}
#endif
/*****************************************************************************
* FUNCTION
* nvram_drv_fat_write
* DESCRIPTION
* write record(s) to FAT.
* PARAMETERS
* buffer [?]
* nvramname [?]
* section_number [IN]
* size [IN]
* initialize [IN] true for reset, false for normal write.
* RETURNS
* void
*****************************************************************************/
nvram_drv_status_enum nvram_drv_fat_write(kal_char *nvramname,
nvram_folder_enum nvram_folder,
kal_uint32 file_offset,
kal_uint16 rec_index,
kal_uint16 rec_amount,
kal_uint32 rec_size,
const kal_uint8 *buffer,
nvram_ltable_entry_struct *ldi,
kal_bool initialize)
{
kal_int32 result = FS_NO_ERROR;
kal_int32 Ret = FS_NO_ERROR;
#ifdef __NVRAM_LID_CACHE__
if(NVRAM_WR_WITH_CACHE(ldi->LID) && (!(NVRAM_IS_ATTR_RAW_DATA(ldi->attr))))
{
result = nvram_drv_fat_write_cache_section(buffer, rec_index, rec_amount, rec_size, ldi);
}
else
#endif
{
/*----------------------------------------------------------------*/
/* Local Variables */
/*----------------------------------------------------------------*/
kal_wchar filename[NVRAM_MAX_PATH_LEN];
FS_HANDLE hFile = 0;
kal_uint32 openOption = FS_READ_WRITE | FS_OPEN_NO_DIR;
kal_uint32 len;
kal_uint32 nvram_chksum_size = 0;
nvram_lid_chksum_info lid_chksum_info = {0};
#if defined(__NVRAM_ACCESS_TIMEOUT_ASSERT__)
SGPT_CTRL_START_T start;
#endif
nvram_ldi_ota_header ota_header;
/*----------------------------------------------------------------*/
/* Code Body */
/*----------------------------------------------------------------*/
/* NVRAM GPT timeout assert start timer */
#if defined(__NVRAM_ACCESS_TIMEOUT_ASSERT__)
start.u2Tick= NVRAM_WRITE_GPT_TIMEOUT;
start.pfCallback=nvram_gpt_timeout_callback;
start.vPara=NULL;
#endif
nvram_util_take_mutex(g_nvram_fs_mutex);
nvram_get_lid_chksum_algo_info(ldi, &lid_chksum_info, KAL_FALSE, KAL_FALSE);
nvram_chksum_size = lid_chksum_info.algo_info.chksum_algo_length;
#if defined(__NVRAM_ACCESS_TIMEOUT_ASSERT__)
DclSGPT_Control(nvram_gpt_handle, SGPT_CMD_START, (DCL_CTRL_DATA_T*)&start); //start timer
#endif
do
{
if (rec_index < 1 || rec_amount < 1)
{
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]%s fail at %d,\r\n",__FUNCTION__,__LINE__);
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]rec_index=%d,rec_amount=%d\r\n",rec_index,rec_amount);
nvram_fat_last_line = __LINE__;
result = NVRAM_DRV_INVALID_RECORD_ID;
break;
}
/* translate record id to filename */
nvram_query_file_name(nvram_folder, nvramname, filename);
/* set the attribute to empty before write data
sometime the files may be read only if the nvram lock is turn on
ex: software update when nvram lock is turned on
But it is not a good solution here, we should unlock it in io layer */
openOption |= FS_CREATE;
if (initialize != KAL_TRUE)
{
#if !defined(_NAND_FLASH_BOOTING_) && !defined(__FS_SYSDRV_ON_NAND__) && !defined(__EMMC_BOOTING__)
openOption |= FS_PROTECTION_MODE; /* boot from NAND and single bank NOR don't support this */
#endif
}
#if defined(__CCCIFS_SUPPORT__) && defined(__MTK_TARGET__)
if (ldi->attr & NVRAM_ATTR_COMMITTED)
{
openOption |= FS_COMMITTED;
}
#endif
NVRAM_FS_START_EX(FS_OP_OPEN,filename);
hFile = FS_Open((const kal_wchar*)filename, openOption);
NVRAM_FS_END(FS_OP_OPEN,hFile);
if (hFile == FS_FILE_NOT_FOUND)
{
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]%s ->FS_Open %s fail\r\n",__FUNCTION__,nvramname);
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]Fail at %d,FS_FILE_NOT_FOUND hFile=%d\r\n",__LINE__,hFile);
nvram_fat_last_line = __LINE__;
result = NVRAM_DRV_EMPTY_RECORD;
break;
}
else if (hFile <= FS_NO_ERROR)
{
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]%s ->FS_Open %s fail \r\n",__FUNCTION__,nvramname);
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]Fail at %d,hFile=%d\r\n",__LINE__,hFile);
nvram_fat_last_line = __LINE__;
result = hFile;
break;
}
//Get appdenix header info
if(ldi->attr & NVRAM_ATTR_CHKSUM_INTEGRATE) {
ldi->append_buffer = get_ctrl_buffer(rec_amount * nvram_chksum_size);
}
if (file_offset)
{
NVRAM_FS_START(FS_OP_SEEK);
result = FS_Seek(hFile, file_offset, FS_FILE_BEGIN);
NVRAM_FS_END(FS_OP_SEEK,result);
if(FS_NO_ERROR > result){
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]%s ->FS_Seek fail at %d,result=%d\r\n",__FUNCTION__,__LINE__,result);
nvram_fat_last_line = __LINE__;
break;
}
}
/* try to write one record in file, but found the file size is zero. strange ! */
if (!(ldi->attr & NVRAM_ATTR_BACKUP_RAW) &&
!NVRAM_IS_ATTR_RAW_DATA(ldi->attr) &&
!initialize
) //only have header, fill content is NULL
{
NVRAM_FS_START(FS_OP_GETFILESIZE);
result = FS_GetFileSize(hFile, &len);
NVRAM_FS_END(FS_OP_GETFILESIZE,result);
if( result == FS_NO_ERROR && (len <= NVRAM_LDI_HEADER_SIZE)){
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]%s ->FS_GetFileSize fail at %d,result=%d\r\n",__FUNCTION__,__LINE__,result);
nvram_fat_last_line = __LINE__;
result = NVRAM_DRV_EMPTY_RECORD;
#if defined(__NVRAM_WRITE_PROTECT_ENABLE__) && defined(__NVRAM_IMPORTANT_PARTITIONS__) && defined(__CCCIFS_SUPPORT__) && defined(__MTK_TARGET__)
if(nvram_folder != NVRAM_NVD_IMPNT2)
{
// Permit to write Y: as the important_l4 data is maybe deleted manualy
break;
}
#else
break;
#endif
}
}
/* Fast reset need to know whether file be written */
if (!(ldi->attr & NVRAM_ATTR_BACKUP_RAW) &&
!NVRAM_IS_ATTR_RAW_DATA(ldi->attr) &&
initialize &&
(buffer == NVRAM_EF_ZERO_DEFAULT))
{
NVRAM_FS_START(FS_OP_GETFILESIZE);
result = FS_GetFileSize(hFile, &len);
NVRAM_FS_END(FS_OP_GETFILESIZE,result);
}
result = nvram_drv_fat_write_section(hFile, buffer, rec_index, rec_amount, rec_size, ldi, len);
}while(0);
//write-back appdenix header info
if(ldi->attr & NVRAM_ATTR_CHKSUM_INTEGRATE) {
if(ldi->append_offset == 0) {
#if defined(__NVRAM_LID_CACHE__) && (defined(__NVRAM_LID_PREREAD__) || defined(__NVRAM_CACHE_BYPASS_W_LIST__))
if(KAL_TRUE == nvram_cache_read_ota_header(filename, hFile, &ota_header, NVRAM_LDI_OTA_HEADER_SIZE) &&
(ota_header.ldi_attr & NVRAM_ATTR_CHKSUM_INTEGRATE) )
#else
if(KAL_TRUE == nvram_read_ota_header(hFile, &ota_header, NVRAM_LDI_OTA_HEADER_SIZE) &&
(ota_header.ldi_attr & NVRAM_ATTR_CHKSUM_INTEGRATE) )
#endif
{
ldi->append_offset = nvram_appendix_header_offset(ldi);
}
else {
ldi->append_offset = -1;
}
}
if(ldi->append_offset > 0) {
NVRAM_FS_START(FS_OP_SEEK);
result = FS_Seek(hFile, (ldi->append_offset + NVRAM_LDI_APPENDIX_HEADER_SIZE + ((rec_index - 1) * nvram_chksum_size)), FS_FILE_BEGIN);
NVRAM_FS_END(FS_OP_SEEK,result);
NVRAM_FS_START(FS_OP_WRITE);
result = FS_Write(hFile, ldi->append_buffer, (rec_amount * nvram_chksum_size), &len);
NVRAM_FS_END(FS_OP_WRITE,result);
#if defined(__NVRAM_LID_CACHE__)
kal_uint32 cache_offset = 0;
if((!NVRAM_IS_ATTR_RAW_DATA(ldi->attr)) && NVRAM_WR_2_FILE_WITH_2_CACHE(ldi->LID))
{
get_lid_cache_base_address(ldi, &cache_offset);
cache_offset = cache_offset + (ldi->append_offset + NVRAM_LDI_APPENDIX_HEADER_SIZE + ((rec_index - 1) * nvram_chksum_size));
nvram_write_data_to_cache(ldi, (kal_uint8*)ldi->append_buffer, (rec_amount * nvram_chksum_size), cache_offset);
}
#endif
}
if(ldi->append_buffer) {
free_ctrl_buffer(ldi->append_buffer);
ldi->append_buffer = NULL;
}
}
if (hFile > FS_NO_ERROR)
{
NVRAM_FS_START(FS_OP_CLOSE);
Ret = FS_Close(hFile);
NVRAM_FS_END(FS_OP_CLOSE,Ret);
}
#if defined(__NVRAM_ACCESS_TIMEOUT_ASSERT__)
DclSGPT_Control(nvram_gpt_handle, SGPT_CMD_STOP, (DCL_CTRL_DATA_T*)NULL); //stop timer
#endif
nvram_util_give_mutex(g_nvram_fs_mutex);
/* Set the attribute back to original attribute */
if (result < FS_NO_ERROR)
{
nvram_fat_last_err = result;
MD_TRC_FUNC_NVRAM_DRV_FAT_THROW_EXCEPTION(nvram_fat_last_err, nvram_fat_last_line);
}
}
return result;
}
nvram_drv_status_enum nvram_drv_fat_write_exception_item(kal_uint8 *buffer,
kal_char *nvramname,
kal_uint16 section_number,
kal_uint32 size,
kal_uint32 writesize)
{
/*----------------------------------------------------------------*/
/* Local Variables */
/*----------------------------------------------------------------*/
kal_wchar filename[NVRAM_MAX_PATH_LEN];
kal_char cfilename[NVRAM_FILE_LEN + 1] = {0};
kal_wchar wcfilename[NVRAM_FILE_LEN + 1] = {0};
FS_HANDLE hFile = 0;
kal_uint32 len = 0;
kal_uint32 offset = 0;
kal_int32 Ret = FS_NO_ERROR;
kal_uint32 nvram_chksum_size = 0;
nvram_ltable_entry_struct *ldi = NULL;
nvram_lid_chksum_info lid_chksum_info = {0};
/*----------------------------------------------------------------*/
/* Code Body */
/*----------------------------------------------------------------*/
if (section_number < 1)
{
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]%s fail at %d,section_number=%d\r\n",__FUNCTION__,__LINE__,section_number);
/* kal_print("Nvram write: section_number < 1 !"); */
return NVRAM_DRV_INVALID_RECORD_ID;
}
/* translate record id to filename */
nvram_query_file_name(NVRAM_NVD_DATA, nvramname, filename);
nvram_query_file_name_by_path((kal_wchar *)filename, wcfilename);
kal_dchar2char((WCHAR *)wcfilename, cfilename);
nvram_util_get_data_item_by_fileprefix(&ldi, cfilename);
nvram_get_lid_chksum_algo_info(ldi, &lid_chksum_info, KAL_FALSE, KAL_FALSE);
nvram_chksum_size = lid_chksum_info.algo_info.chksum_algo_length;
if(nvram_chksum_size > sizeof(g_chksum))
{
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]%s-> %d nvram_chksum_size > chksum array size.\r\n",__FUNCTION__, __LINE__);
}
/* open NV_RCD.(RCD#) file */
NVRAM_FS_START_EX(FS_OP_OPEN,filename);
hFile = FS_Open((const kal_wchar*)filename, FS_CREATE | FS_READ_WRITE | FS_OPEN_NO_DIR);
NVRAM_FS_END(FS_OP_OPEN,hFile);
if (hFile == FS_FILE_NOT_FOUND)
{
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]%s->FS_Open %s fail\r\n",__FUNCTION__,nvramname);
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]Fail at %d,FS_FILE_NOT_FOUND hFile=%d\r\n",__LINE__,hFile);
return NVRAM_DRV_EMPTY_RECORD;
}
else if (hFile <= FS_NO_ERROR)
{
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]%s->FS_Open %s fail\r\n",__FUNCTION__,nvramname);
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]Fail at %d,hFile=%d\r\n",__LINE__,hFile);
/* kal_print("Nvram write: FS_Open return error!"); */
return NVRAM_DRV_FATAL_ERROR;
}
/* seek to the record start */
offset = NVRAM_LDI_HEADER_SIZE;
offset += (section_number - 1) * (size + nvram_chksum_size);
NVRAM_FS_START(FS_OP_SEEK);
Ret = FS_Seek(hFile, offset, FS_FILE_BEGIN);
NVRAM_FS_END(FS_OP_SEEK,Ret);
if (Ret == offset)
{
NVRAM_FS_START(FS_OP_WRITE);
Ret = FS_Write(hFile, buffer, (kal_uint32) writesize, &len);
NVRAM_FS_END(FS_OP_WRITE,Ret);
if (Ret == FS_NO_ERROR)
{
nvram_util_caculate_checksum(ldi, buffer, writesize,g_chksum);
NVRAM_FS_START(FS_OP_WRITE);
Ret = FS_Write(hFile, g_chksum, nvram_chksum_size, &len);
NVRAM_FS_END(FS_OP_WRITE,Ret);
}
}
if (Ret != FS_NO_ERROR)
{
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]%s fail at %d,result=%d\r\n",__FUNCTION__,__LINE__,Ret);
/* kal_print("Nvram write: Read error!"); */
NVRAM_FS_START(FS_OP_CLOSE);
Ret = FS_Close(hFile);
NVRAM_FS_END(FS_OP_CLOSE,Ret);
return NVRAM_DRV_CHECKSUM_ERROR;
}
NVRAM_FS_START(FS_OP_CLOSE);
Ret = FS_Close(hFile);
NVRAM_FS_END(FS_OP_CLOSE,Ret);
return NVRAM_DRV_OK;
}
/*****************************************************************************
* FUNCTION
* nvram_drv_fat_get_record_size
* DESCRIPTION
* get the record size.
* PARAMETERS
* nvramname [?]
* Hint [?]
* RETURNS
* void
*****************************************************************************/
kal_int32 nvram_drv_fat_get_record_size(kal_char *nvramname, void *Hint, nvram_folder_enum nvram_folder)
{
kal_wchar filename[NVRAM_MAX_PATH_LEN];
kal_uint32 size = 0;
kal_int32 Ret = FS_NO_ERROR;
#if !defined(__NVRAM_FS_OPERATION_COMPACT__) || !(defined(__CCCIFS_SUPPORT__) && defined(__MTK_TARGET__))
FS_HANDLE hFile;
nvram_query_file_name(nvram_folder, nvramname, filename);
nvram_util_take_mutex(g_nvram_fs_mutex);
NVRAM_FS_START_EX(FS_OP_OPENHINT,filename);
hFile = FS_OpenHint(filename, FS_READ_ONLY, (FS_FileOpenHint*) Hint);
NVRAM_FS_END(FS_OP_OPENHINT,hFile);
if ( hFile > 0)
{
NVRAM_FS_START(FS_OP_GETFILESIZE);
Ret = FS_GetFileSize(hFile, &size);
NVRAM_FS_END(FS_OP_GETFILESIZE,Ret);
if (Ret != FS_NO_ERROR)
{
size = 0;
}
NVRAM_FS_START(FS_OP_CLOSE);
Ret = FS_Close(hFile);
NVRAM_FS_END(FS_OP_CLOSE,Ret);
nvram_util_give_mutex(g_nvram_fs_mutex);
return (size - NVRAM_LDI_HEADER_SIZE);
}
else
{
nvram_util_give_mutex(g_nvram_fs_mutex);
return hFile;
}
#else
NVRAM_FS_PARAM_CMPT_T nvram_param;
#if defined(__NVRAM_ACCESS_TIMEOUT_ASSERT__)
SGPT_CTRL_START_T start;
#endif
nvram_query_file_name(nvram_folder, nvramname, filename);
/* Add NVRAM GPT timeout assert start timer*/
#if defined(__NVRAM_ACCESS_TIMEOUT_ASSERT__)
start.u2Tick= NVRAM_READ_GPT_TIMEOUT;
start.pfCallback=nvram_gpt_timeout_callback;
start.vPara=NULL;
#endif
nvram_util_take_mutex(g_nvram_fs_mutex);
#if defined(__NVRAM_ACCESS_TIMEOUT_ASSERT__)
DclSGPT_Control(nvram_gpt_handle, SGPT_CMD_START, (DCL_CTRL_DATA_T*)&start); //start timer
#endif
nvram_param.opid_map = 0;
nvram_param.ret[0] = 0;
nvram_param.ret[1] = 0;
//FS_Open
nvram_param.opid_map |= NVRAM_FS_CMPT_OPEN;
nvram_param.Flag = FS_READ_ONLY;
//FS_GetFileSize
nvram_param.opid_map |= NVRAM_FS_CMPT_GETFILESIZE;
nvram_param.FileSize = &size;
nvram_param.DataPtr = NULL;
nvram_param.Read = NULL;
//FS_Close
nvram_param.opid_map |= NVRAM_FS_CMPT_CLOSE;
NVRAM_FS_START_EX(FS_OP_CMPTREAD,filename);
Ret = FS_CMPT_Read(filename, &nvram_param);
NVRAM_FS_END(FS_OP_CMPTREAD,Ret);
#if defined(__NVRAM_ACCESS_TIMEOUT_ASSERT__)
DclSGPT_Control(nvram_gpt_handle, SGPT_CMD_STOP, (DCL_CTRL_DATA_T*)NULL); //stop timer
#endif
nvram_util_give_mutex(g_nvram_fs_mutex);
if (nvram_param.opid_map == nvram_param.ret[0])
{
return (size - NVRAM_LDI_HEADER_SIZE);
}
else
{
return nvram_param.ret[1];
}
#endif
}
#if (defined(__CCCIFS_SUPPORT__) && defined(__MTK_TARGET__)) || defined(__NVRAM_BIN_REGION_SIMULATION__)
#ifdef __NVRAM_CHECK_FILE_AND_RECOVER__
static kal_int32 nvram_drv_fat_read_file(const kal_wchar* filename, void *DataPtr, kal_uint32 *Readlen)
{
kal_int32 result = 0;
FS_HANDLE hFile = 0;
kal_uint32 len;
kal_int32 Ret = 0;
do
{
NVRAM_FS_START_EX(FS_OP_OPEN,filename);
hFile = FS_Open(filename, FS_READ_ONLY | FS_OPEN_NO_DIR | FS_OPEN_SHARED);
NVRAM_FS_END(FS_OP_OPEN,hFile);
if (hFile == FS_FILE_NOT_FOUND)
{
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]%s ->FS_Open fail at %d,hFile=%d\r\n",__FUNCTION__,__LINE__,hFile);
nvram_fat_last_line = __LINE__;
result = NVRAM_DRV_EMPTY_RECORD;
break;
}
else if (hFile <= FS_NO_ERROR)
{
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]%s ->FS_Open fail at %d,hFile=%d\r\n",__FUNCTION__,__LINE__,hFile);
nvram_fat_last_line = __LINE__;
result = NVRAM_DRV_FATAL_ERROR;
break;
}
/* check if a empty record */
NVRAM_FS_START(FS_OP_GETFILESIZE);
result = FS_GetFileSize(hFile, &len);
NVRAM_FS_END(FS_OP_GETFILESIZE,result);
if ((result == FS_NO_ERROR) && (len == 0))
{
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]%s ->FS_GetFileSize fail at %d,result=%d\r\n",__FUNCTION__,__LINE__,result);
NVRAM_FS_START(FS_OP_CLOSE);
Ret = FS_Close(hFile);
NVRAM_FS_END(FS_OP_CLOSE,Ret);
nvram_fat_last_line = __LINE__;
result = NVRAM_DRV_EMPTY_RECORD;
break;
}
NVRAM_FS_START(FS_OP_SEEK);
result = FS_Seek(hFile, 0, FS_FILE_BEGIN);
NVRAM_FS_END(FS_OP_SEEK,result);
if (FS_NO_ERROR > result)
{
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]%s ->FS_Seek fail at %d,result=%d\r\n",__FUNCTION__,__LINE__,result);
NVRAM_FS_START(FS_OP_CLOSE);
Ret = FS_Close(hFile);
NVRAM_FS_END(FS_OP_CLOSE,Ret);
nvram_fat_last_line = __LINE__;
break;
}
NVRAM_FS_START(FS_OP_READ);
result = FS_Read(hFile, DataPtr, len, Readlen);
NVRAM_FS_END(FS_OP_READ,result);
if (hFile > FS_NO_ERROR)
{
NVRAM_FS_START(FS_OP_CLOSE);
Ret = FS_Close(hFile);
NVRAM_FS_END(FS_OP_CLOSE,Ret);
}
}while(0);
return result;
}
#endif
/*****************************************************************************
* FUNCTION
* nvram_drv_fat_auto_recover
* DESCRIPTION
* file auto-recover, only for smart phone.
* PARAMETERS
* filename [IN] full path of the data item
* rec_index [IN] which record to read (start)
* rec_amount [IN] how many record to read at once
* rec_size [IN] size of record
* buffer [IN/OUT] buffer of check sum
* type [IN] read content or checksum
* ismsp [IN] to indicate that the records protected by hw
* RETURNS
* = 0: success
* > 0: NVRAM error code
* < 0: FS error code
*****************************************************************************/
kal_int32 nvram_drv_fat_auto_recover(
kal_char *nvramname,
nvram_folder_enum nvram_folder /* folder index */
)
{
/*----------------------------------------------------------------*/
/* Local Variables */
/*----------------------------------------------------------------*/
kal_int32 result = 0;
kal_wchar filename[NVRAM_MAX_PATH_LEN];
kal_char cfilename[NVRAM_FILE_LEN + 1];
kal_wchar wcfilename[NVRAM_FILE_LEN + 1];
void *dummy_ptr = (void*)&result;
FS_HANDLE fhdl = FS_INVALID_FILE_HANDLE;
#ifdef __NVRAM_CHECK_FILE_AND_RECOVER__
kal_wchar *Cali_filelistname = NULL;
kal_wchar *Imei_filelistname = NULL;
nvram_folder_enum folder_index;
kal_uint32 len = 0;
kal_int32 temp_count = 0;
#endif
nvram_ldi_header nv_header;
kal_uint32 header_buffer_size = 0;
nvram_ltable_entry_struct *ldi = NULL;
kal_int32 ret = 0;
/*----------------------------------------------------------------*/
/* Code Body */
/*----------------------------------------------------------------*/
nvram_util_take_mutex(g_nvram_fs_mutex);
nvram_query_file_name(nvram_folder, nvramname, filename);
#if defined(__NVRAM_BIN_REGION_SIMULATION__)
{
kal_wchar *s_filename = (kal_wchar *)get_ctrl_buffer(NVRAM_MAX_PATH_LEN * sizeof(kal_wchar));
kal_wsprintf(s_filename, "%s\\%s", "Z:\\BIN_REGION", nvramname);
NVRAM_FS_START_EX(FS_OP_MOVE,s_filename);
result = FS_Move(s_filename, filename, (FS_MOVE_COPY | FS_MOVE_OVERWRITE), NULL, NULL, 0);
NVRAM_FS_END(FS_OP_MOVE,result);
free_ctrl_buffer(s_filename);
s_filename = NULL;
}while(0);
#else
#ifdef __NVRAM_CHECK_FILE_AND_RECOVER__
if(is_nvram_in_ota_flow)
{
if(is_nvram_first_restore)
{
Cali_filelistname = (kal_wchar *)get_ctrl_buffer(NVRAM_MAX_PATH_LEN * sizeof(kal_wchar));
Imei_filelistname = (kal_wchar *)get_ctrl_buffer(NVRAM_MAX_PATH_LEN * sizeof(kal_wchar));
if(Cali_filelistname == NULL)
{
kal_prompt_trace(MOD_NVRAM, "%s Can not get the memory from control buffer @line %d\n\r",__FUNCTION__,__LINE__);
}
if(Imei_filelistname == NULL)
{
kal_prompt_trace(MOD_NVRAM, "%s Can not get the memory from control buffer @line %d\n\r",__FUNCTION__,__LINE__);
}
folder_index = nvram_query_folder_index(NVRAM_CATEGORY_CALIBRAT);
nvram_query_file_name(folder_index, "FILELIST", Cali_filelistname);
folder_index = nvram_query_folder_index(NVRAM_CATEGORY_IMPORTANT);
nvram_query_file_name(folder_index, "FILELIST", Imei_filelistname);
//delete FILELIST in Calibrate and IMEI folder
NVRAM_FS_START_EX(FS_OP_XDELETE,Cali_filelistname);
ret = MD_FS_Delete((const kal_wchar*)Cali_filelistname);
NVRAM_FS_END(FS_OP_XDELETE,ret);
NVRAM_FS_START_EX(FS_OP_XDELETE, Imei_filelistname);
ret = MD_FS_Delete((const kal_wchar*)Imei_filelistname);
NVRAM_FS_END(FS_OP_XDELETE,ret);
//Restore FILELIST from bin region
NVRAM_FS_START_EX(FS_OP_RESTORE,Cali_filelistname);
result = MD_FS_Restore((const kal_wchar*)Cali_filelistname, dummy_ptr, 4);
NVRAM_FS_END(FS_OP_RESTORE,result);
if(result >= 0)
{
//read filelist from bin region to buf
result = nvram_drv_fat_read_file((const kal_wchar* )Cali_filelistname, (void *)CALI_FileListBuf,&len);
if(result == 0)
{
Cali_filelist_found = KAL_TRUE;
for(temp_count = 0; temp_count < len; temp_count++)
{
if(CALI_FileListBuf[temp_count] == 0x00)
{
CALI_FileListBuf[temp_count] = 0xd;
}
}
}
}
NVRAM_FS_START_EX(FS_OP_RESTORE, Imei_filelistname);
result = MD_FS_Restore((const kal_wchar*)Imei_filelistname, dummy_ptr, 4);
NVRAM_FS_END(FS_OP_RESTORE,result);
if(result >= 0)
{
//read filelist from bin region to buf
result = nvram_drv_fat_read_file((const kal_wchar* )Imei_filelistname, (void *)IMEI_FileListBuf,&len);
if(result == 0)
{
Imei_filelist_found = KAL_TRUE;
for(temp_count = 0; temp_count < len; temp_count++)
{
if(IMEI_FileListBuf[temp_count] == 0x00)
{
IMEI_FileListBuf[temp_count] = 0xd;
}
}
}
}
is_nvram_first_restore = KAL_FALSE;
free_ctrl_buffer(Cali_filelistname);
free_ctrl_buffer(Imei_filelistname);
Cali_filelistname = NULL;
Imei_filelistname = NULL;
}
if((NVRAM_NVD_IMPT == nvram_folder) &&(Imei_filelist_found == KAL_TRUE))
{
if(NULL != strstr((const char *)IMEI_FileListBuf,(const char *)nvramname))
{
NVRAM_FS_START_EX(FS_OP_RESTORE, filename);
result = MD_FS_Restore((const kal_wchar*)filename, dummy_ptr, 4);
NVRAM_FS_END(FS_OP_RESTORE,result);
}
else
{
result = NVRAM_DRV_FATAL_ERROR;
}
}
else if((NVRAM_NVD_CALI == nvram_folder)&&(Cali_filelist_found == KAL_TRUE))
{
if(NULL != strstr((const char *)CALI_FileListBuf,(const char *)nvramname))
{
NVRAM_FS_START_EX(FS_OP_RESTORE, filename);
result = MD_FS_Restore((const kal_wchar*)filename, dummy_ptr, 4);
NVRAM_FS_END(FS_OP_RESTORE,result);
}
else
{
result = NVRAM_DRV_FATAL_ERROR;
}
}
else
{
result = NVRAM_DRV_FATAL_ERROR;
}
}
else
{
NVRAM_FS_START_EX(FS_OP_RESTORE, filename);
result = MD_FS_Restore((const kal_wchar*)filename, dummy_ptr, 4);
NVRAM_FS_END(FS_OP_RESTORE,result);
}
#else
NVRAM_FS_START_EX(FS_OP_RESTORE, filename);
result = MD_FS_Restore((const kal_wchar*)filename, dummy_ptr, 4);
NVRAM_FS_END(FS_OP_RESTORE,result);
#endif
kal_mem_set(&nv_header, 0x0, sizeof(nv_header));
if(result == NVRAM_DRV_OK)
{
NVRAM_FS_START_EX(FS_OP_OPEN, filename);
fhdl = FS_Open(filename, FS_READ_ONLY | FS_OPEN_SHARED |FS_OPEN_NO_DIR);
NVRAM_FS_END(FS_OP_OPEN,result);
if(fhdl > FS_NO_ERROR)
{
NVRAM_FS_START(FS_OP_READ);
result = FS_Read(fhdl, &nv_header, NVRAM_LDI_HEADER_SIZE, &header_buffer_size);
NVRAM_FS_END(FS_OP_READ,result);
}
if((fhdl > FS_NO_ERROR) && (result == NVRAM_DRV_OK))
{
NVRAM_FS_START(FS_OP_SEEK);
ret = FS_Seek(fhdl, 0, FS_FILE_BEGIN);
NVRAM_FS_END(FS_OP_SEEK,result);
}
if((fhdl > FS_NO_ERROR) && (strcmp(nv_header.nv_ota_header.header,"LDI"))){
ldi = NULL;
kal_mem_set(cfilename,0,NVRAM_FILE_LEN + 1);
kal_mem_set(wcfilename,0,(NVRAM_FILE_LEN + 1)*sizeof(kal_wchar));
nvram_query_file_name_by_path((kal_wchar *)filename, wcfilename);
kal_dchar2char((WCHAR *)wcfilename, cfilename);
nvram_util_get_data_item_by_fileprefix(&ldi, cfilename);
if(ldi != NULL)
{
nvram_prepare_data_header(ldi, (kal_uint8 *)(&nv_header));
NVRAM_FS_START(FS_OP_WRITE);
result = FS_Write(fhdl, (void *)(&nv_header), NVRAM_LDI_HEADER_SIZE, &header_buffer_size);
NVRAM_FS_END(FS_OP_WRITE,result);
}
}
if(fhdl > FS_NO_ERROR) {
NVRAM_FS_START(FS_OP_CLOSE);
ret = FS_Close(fhdl);
NVRAM_FS_END(FS_OP_CLOSE,ret);
}
}
#endif
nvram_util_give_mutex(g_nvram_fs_mutex);
#ifdef __NVRAM_LID_CACHE__
{
ldi = NULL;
kal_mem_set(cfilename,0,NVRAM_FILE_LEN + 1);
kal_mem_set(wcfilename,0,(NVRAM_FILE_LEN + 1)*sizeof(kal_wchar));
nvram_query_file_name_by_path((kal_wchar *)filename, wcfilename);
kal_dchar2char((WCHAR *)wcfilename, cfilename);
nvram_util_get_data_item_by_fileprefix(&ldi, cfilename);
if(ldi == NULL)
{
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]Can't find LID entry for %s in the LID table\r\n",cfilename);
if(nvram_ptr->state == NVRAM_STATE_READY)
{
kal_prompt_trace(MOD_NVRAM, "cfilename:%s\n\r", cfilename);
kal_prompt_trace(MOD_NVRAM, "Can't find LID entry in the LID table:\n\r");
NVRAM_EXT_ASSERT(KAL_FALSE,0 , NVRAM_LOC_LID_PTR_IS_NULL_3, ldi);
}else
{
kal_prompt_trace(MOD_NVRAM, "cfilename:%s\n\r", cfilename);
return NVRAM_DRV_FATAL_ERROR;
}
}
if((!NVRAM_IS_ATTR_RAW_DATA(ldi->attr)) && NVRAM_RD_WITH_CACHE(ldi->LID))
{
unmask_valid_bit_by_ltable_entry(ldi, 0, (ldi->total_records + 1));
}
}
#endif
return result;
}
#endif
#ifdef __NVRAM_LID_CACHE__
/*****************************************************************************
* FUNCTION
* nvram_drv_fat_write_cache_section
* DESCRIPTION
* write record(s) to FAT.
* PARAMETERS
* buffer [?]
* nvramname [?]
* section_number [IN]
* size [IN]
* initialize [IN] true for reset, false for normal write.
* RETURNS
* void
*****************************************************************************/
nvram_drv_status_enum nvram_drv_fat_write_cache_section(
const kal_uint8 *buffer,
kal_uint16 rec_index,
kal_uint16 rec_amount,
kal_uint32 rec_size,
nvram_ltable_entry_struct *ldi)
{
/*----------------------------------------------------------------*/
/* Local Variables */
/*----------------------------------------------------------------*/
kal_uint32 openOption = FS_READ_WRITE | FS_OPEN_NO_DIR;
kal_uint32 remainLen = 0;
kal_uint8 *chksum = NULL;
kal_uint32 max_rec_amount = 0;
kal_uint32 section_size = 0;
kal_uint32 working_buffer_size = 0;
kal_uint8 *working_buffer = NULL;
kal_int32 result = NVRAM_IO_ERRNO_OK;
kal_bool encrypt_data = KAL_FALSE;
kal_uint32 i = 0;
kal_uint16 temp_rec_index = rec_index;
kal_uint32 cache_offset = 0;
kal_uint32 temp_cache_offset = 0;
kal_uint32 nvram_chksum_size = 0;
nvram_lid_chksum_info lid_chksum_info = {0};
#if defined(__NVRAM_ACCESS_TIMEOUT_ASSERT__)
SGPT_CTRL_START_T start;
#endif
/*----------------------------------------------------------------*/
/* Code Body */
/*----------------------------------------------------------------*/
/* NVRAM GPT timeout assert start timer */
#if defined(__NVRAM_ACCESS_TIMEOUT_ASSERT__)
start.u2Tick= NVRAM_WRITE_GPT_TIMEOUT;
start.pfCallback=nvram_gpt_timeout_callback;
start.vPara=NULL;
#endif
//nvram_util_take_mutex(g_nvram_fs_mutex);
#if defined(__NVRAM_ACCESS_TIMEOUT_ASSERT__)
DclSGPT_Control(nvram_gpt_handle, SGPT_CMD_START, (DCL_CTRL_DATA_T*)&start); //start timer
#endif
nvram_get_lid_chksum_algo_info(ldi, &lid_chksum_info, KAL_FALSE, KAL_FALSE);
nvram_chksum_size = lid_chksum_info.algo_info.chksum_algo_length;
/* set the attribute to empty before write data
sometime the files may be read only if the nvram lock is turn on
ex: software update when nvram lock is turned on
But it is not a good solution here, we should unlock it in io layer */
openOption |= FS_CREATE;
#if !defined(_NAND_FLASH_BOOTING_) && !defined(__FS_SYSDRV_ON_NAND__) && !defined(__EMMC_BOOTING__)
openOption |= FS_PROTECTION_MODE; /* boot from NAND and single bank NOR don't support this */
#endif
#if defined(__CCCIFS_SUPPORT__) && defined(__MTK_TARGET__)
if (ldi->attr & NVRAM_ATTR_COMMITTED) {
openOption |= FS_COMMITTED;
}
#endif
//Get appdenix header info
if(ldi->attr & NVRAM_ATTR_CHKSUM_INTEGRATE) {
ldi->append_buffer = get_ctrl_buffer(rec_amount * nvram_chksum_size);
}
#ifdef __NVRAM_BIND_TO_CHIP_CIPHER__
if ((ldi->attr & NVRAM_ATTR_MSP)||(ldi->attr & NVRAM_ATTR_CONFIDENTIAL)) {
/* 16 byte alignment */
remainLen = NVRAM_MSP_ALIGNMENT_REMAINDER(rec_size + nvram_chksum_size);
encrypt_data = KAL_TRUE;
}
#else
if (ldi->attr & NVRAM_ATTR_CONFIDENTIAL) {
/* 16 byte alignment */
remainLen = NVRAM_MSP_ALIGNMENT_REMAINDER(rec_size + nvram_chksum_size);
encrypt_data = KAL_TRUE;
}
#endif
section_size = rec_size + nvram_chksum_size + remainLen;
working_buffer_size = section_size * rec_amount;
if (working_buffer_size > MAX_NVRAM_RECORD_SIZE) {
working_buffer_size = MAX_NVRAM_RECORD_SIZE;
}
working_buffer = (kal_uint8*) get_ctrl_buffer(working_buffer_size);
chksum = (kal_uint8*) get_ctrl_buffer(nvram_chksum_size);
/* we can write data into FS directly, we don't need another buffer*/
if (!(ldi->attr & NVRAM_ATTR_MSP) && !(ldi->attr & NVRAM_ATTR_CONFIDENTIAL) &&
#if defined(__MTK_TARGET__) && defined(__NVRAM_IMPORTANT_PARTITIONS__)
!(ldi->attr & NVRAM_ATTR_COMMITTED) &&
#endif
buffer != NVRAM_EF_ZERO_DEFAULT && buffer != NVRAM_EF_FF_DEFAULT)
{
if(NVRAM_IO_ERRNO_OK !=(result = get_lid_record_cache_offset(ldi, rec_index, section_size, &cache_offset))) {
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]%s->get_lid_record_cache_offset fail at %d,result=%d\r\n",__FUNCTION__,__LINE__,result);
result = NVRAM_DRV_INVALID_RECORD_ID;
nvram_fat_last_line = __LINE__;
goto final;
}
for(i = 0;i < rec_amount;i++)
{
nvram_memset(working_buffer, (kal_uint8) NVRAM_EF_ZERO_DEFAULT_VALUE, working_buffer_size);
if ((i == 0) || (ldi->attr & NVRAM_ATTR_MULTI_DEFAULT))
{
kal_mem_set(chksum, 0, nvram_chksum_size);
nvram_util_caculate_checksum(ldi, buffer + i * rec_size, rec_size, chksum);
}
if (ldi->attr & NVRAM_ATTR_MULTI_DEFAULT)
{
kal_mem_cpy(working_buffer, (void *)(buffer + i * rec_size), rec_size);
}else
{
kal_mem_cpy(working_buffer, (void *)buffer, rec_size);
}
//write data & checksum
kal_mem_cpy((void *)(working_buffer + rec_size), (void *)chksum, nvram_chksum_size);
if (NVRAM_IO_ERRNO_OK != (result = nvram_write_data_to_cache(ldi, working_buffer, section_size, (cache_offset + i * section_size)))) {
result = NVRAM_DRV_INVALID_RECORD_ID;
nvram_fat_last_line = __LINE__;
goto final;
}
mask_dirty_bit_by_ltable_entry(ldi, rec_index + i, 1);
mask_valid_bit_by_ltable_entry(ldi, rec_index + i, 1);
//record integrated checksum
if((ldi->attr & NVRAM_ATTR_CHKSUM_INTEGRATE) && ldi->append_buffer) {
kal_mem_cpy((void *)(ldi->append_buffer + (i* nvram_chksum_size)), (void *)chksum, nvram_chksum_size);
}
}
goto final;
}
//working_buffer_size = MAX_NVRAM_RECORD_SIZE;
//MAX_NVRAM_RECORD_SIZE = (NVRAM_CUSTOM_CFG_MAX_RECORD_SECTOR_NUM * NVRAM_RECORD_SECTOR_SIZE)
// = (16 or 4) * 512
#ifdef __NVRAM_LARGE_RECORD_SIZE__
/* size too large , we need to operate block by block */
if (section_size > working_buffer_size)
{
/* we need to prepare extra working buffer;
and due to msp need 16-bytes alignment, therefore
we set the working buffer to 16-bytes alignment also */
kal_uint8 *tmpchksum = NULL;
kal_int32 j,cs_idx;
working_buffer_size = NVRAM_MSP_ALIGNMENT_FLOOR(working_buffer_size) - NVRAM_MSP_ALIGNMENT;
tmpchksum = (kal_uint8*) get_ctrl_buffer(nvram_chksum_size);
if(NVRAM_IO_ERRNO_OK !=(result = get_lid_record_cache_offset(ldi, rec_index, section_size, &cache_offset))) {
result = NVRAM_DRV_INVALID_RECORD_ID;
nvram_fat_last_line = __LINE__;
if (tmpchksum)
{
free_ctrl_buffer(tmpchksum);
tmpchksum = NULL;
}
goto final;
}
for (i = 0 ; i < rec_amount; i++)
{
temp_cache_offset = cache_offset + i*section_size;
for (j = 0; j < rec_size; j += working_buffer_size)
{
kal_int32 byte_in_block = rec_size - j;
kal_bool last_block = KAL_FALSE;
if (byte_in_block > working_buffer_size) {
byte_in_block = working_buffer_size;
if (!(ldi->attr & NVRAM_ATTR_MULTI_DEFAULT)) {
nvram_drv_fat_prepare_data(working_buffer, buffer, j, byte_in_block);
}
else {
nvram_drv_fat_prepare_data(working_buffer, buffer, i * rec_size + j, byte_in_block);
}
}
else /* last block */
{
if (!(ldi->attr & NVRAM_ATTR_MULTI_DEFAULT)) {
nvram_drv_fat_prepare_data(working_buffer, buffer, j, byte_in_block);
}
else {
nvram_drv_fat_prepare_data(working_buffer, buffer, i * rec_size + j, byte_in_block);
}
last_block = KAL_TRUE;
}
if (i == 0 || ldi->attr & NVRAM_ATTR_MULTI_DEFAULT) {
if (j == 0) {
kal_mem_set(chksum, 0, nvram_chksum_size);
}
kal_mem_set(tmpchksum, 0, nvram_chksum_size);
nvram_util_caculate_checksum(ldi, working_buffer, byte_in_block, tmpchksum);
for(cs_idx= 0; cs_idx < nvram_chksum_size;cs_idx++) {
chksum[cs_idx] += tmpchksum[cs_idx];
}
}
/* last block */
if (last_block) {
kal_mem_cpy(working_buffer + byte_in_block, chksum, nvram_chksum_size);
kal_mem_set(working_buffer + byte_in_block + nvram_chksum_size, 0, remainLen);
byte_in_block += (nvram_chksum_size + remainLen);
}
if (ldi->attr & NVRAM_ATTR_CONFIDENTIAL) {
//custom_nvram_encrypt(nvram_ptr->secret_key, working_buffer, byte_in_block, rec_size);
nvram_AES_encrypt(working_buffer, byte_in_block);
}
#ifdef __NVRAM_BIND_TO_CHIP_CIPHER__
if (ldi->attr & NVRAM_ATTR_MSP) {
SST_Secure_Algo(NVRAM_MSP_ENCRYPT, (kal_uint32)working_buffer, byte_in_block, nvram_ptr->secret_key, working_buffer);
}
#endif
if (NVRAM_IO_ERRNO_OK != (result = nvram_write_data_to_cache(ldi, working_buffer, byte_in_block, temp_cache_offset))) {
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"%s->nvram_write_data_to_cache fail at %d,result=%d\r\n",__FUNCTION__,__LINE__,result);
result = NVRAM_DRV_INVALID_RECORD_ID;
nvram_fat_last_line = __LINE__;
if (tmpchksum)
{
free_ctrl_buffer(tmpchksum);
tmpchksum = NULL;
}
goto final;
}
temp_cache_offset = temp_cache_offset + byte_in_block;
}
mask_dirty_bit_by_ltable_entry(ldi, rec_index + i, 1);
mask_valid_bit_by_ltable_entry(ldi, rec_index + i, 1);
//record integrated checksum
if((ldi->attr & NVRAM_ATTR_CHKSUM_INTEGRATE) && ldi->append_buffer) {
kal_mem_cpy((void *)(ldi->append_buffer + (i* nvram_chksum_size)), (void *)chksum, nvram_chksum_size);
}
}
if (tmpchksum)
{
free_ctrl_buffer(tmpchksum);
tmpchksum = NULL;
}
}
else
#endif
{
kal_uint32 rec_in_block = 0;
max_rec_amount = working_buffer_size / section_size;
temp_rec_index = rec_index;
if(NVRAM_IO_ERRNO_OK !=(result = get_lid_record_cache_offset(ldi, rec_index, section_size, &cache_offset))) {
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]%s->get_lid_record_cache_offset fail at %d,result=%d\r\n",__FUNCTION__,__LINE__,result);
result = NVRAM_DRV_INVALID_RECORD_ID;
nvram_fat_last_line = __LINE__;
goto final;
}
for (i = 0; i < rec_amount ; i ++) {
/*
* Write several record at once to reduce io Write
* case a: all remain record
* section_number - i
* case b: max record we can write in one time
* max_rec_amount
* check which case is smaller
*/
nvram_drv_fat_prepare_data(working_buffer + rec_in_block * section_size, buffer, i * rec_size, rec_size);
kal_mem_set(chksum, 0, nvram_chksum_size);
nvram_util_caculate_checksum(ldi, working_buffer + rec_in_block * section_size, rec_size, chksum);
kal_mem_cpy(working_buffer + rec_in_block * section_size + rec_size, chksum, nvram_chksum_size);
if (remainLen) {
kal_mem_set(working_buffer + rec_in_block * section_size + rec_size + nvram_chksum_size , 0x00, remainLen);
}
if (ldi->attr & NVRAM_ATTR_CONFIDENTIAL) {
#ifdef __NVRAM_CRYPT_TEST__
if (bWriteMsp == 1) {
kal_mem_cpy(&NVRAM_EF_MSP_TEST_W,working_buffer,NVRAM_MSP_TEST_LEN);
}
#endif
nvram_AES_encrypt(working_buffer + rec_in_block * section_size, section_size);
#ifdef __NVRAM_CRYPT_TEST__
if (bWriteMsp == 1){
kal_mem_cpy(&NVRAM_EF_MSP_TEST_W[NVRAM_MSP_TEST_LEN],working_buffer,NVRAM_MSP_TEST_LEN);
}
#endif
}
#ifdef __NVRAM_BIND_TO_CHIP_CIPHER__
if (ldi->attr & NVRAM_ATTR_MSP) {
SST_Secure_Algo(NVRAM_MSP_ENCRYPT, (kal_uint32)working_buffer + rec_in_block * section_size, section_size, nvram_ptr->secret_key, working_buffer + rec_in_block * section_size);
}
#endif
//record integrated checksum
if((ldi->attr & NVRAM_ATTR_CHKSUM_INTEGRATE) && ldi->append_buffer) {
kal_mem_cpy((void *)(ldi->append_buffer + (i* nvram_chksum_size)), (void *)chksum, nvram_chksum_size);
}
/* if this is not multi default, no need to prepare data anymore */
if (!(ldi->attr & NVRAM_ATTR_MULTI_DEFAULT)) {
break;
}
rec_in_block ++;
if (rec_in_block == max_rec_amount || i == rec_amount - 1)
{
result = nvram_write_data_to_cache(ldi, working_buffer, section_size * rec_in_block, cache_offset);
if (NVRAM_IO_ERRNO_OK != result)
{
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]%s->nvram_write_data_to_cache fail at %d,result=%d\r\n",__FUNCTION__,__LINE__,result);
result = NVRAM_DRV_INVALID_RECORD_ID;
nvram_fat_last_line = __LINE__;
goto final;
}
mask_dirty_bit_by_ltable_entry(ldi, temp_rec_index, rec_in_block);
mask_valid_bit_by_ltable_entry(ldi, temp_rec_index, rec_in_block);
cache_offset += section_size * rec_in_block;
temp_rec_index += rec_in_block;
rec_in_block = 0;
}
}
/* special handling for not multi default */
if (!(ldi->attr & NVRAM_ATTR_MULTI_DEFAULT)) {
/* special handling for NVRAM_EF_ZERO_DEFAULT write speed up*/
if((buffer == NVRAM_EF_ZERO_DEFAULT) &&
!encrypt_data )
{
if(NVRAM_IO_ERRNO_OK !=(result = get_lid_record_cache_offset(ldi, rec_index, section_size, &cache_offset))) {
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]%s->get_lid_record_cache_offset fail at %d,result=%d\r\n",__FUNCTION__,__LINE__,result);
result = NVRAM_DRV_INVALID_RECORD_ID;
nvram_fat_last_line = __LINE__;
goto final;
}
for(i = 0; i < rec_amount; i++) {
temp_cache_offset = cache_offset + i* section_size;
if (NVRAM_IO_ERRNO_OK != (result = nvram_write_data_to_cache(ldi, working_buffer, section_size, temp_cache_offset))) {
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]%s->nvram_write_data_to_cache fail at %d,result=%d\r\n",__FUNCTION__,__LINE__,result);
result = NVRAM_DRV_INVALID_RECORD_ID;
nvram_fat_last_line = __LINE__;
goto final;
}
mask_dirty_bit_by_ltable_entry(ldi, rec_index + i, 1);
mask_valid_bit_by_ltable_entry(ldi, rec_index + i, 1);
//record integrated checksum
if((ldi->attr & NVRAM_ATTR_CHKSUM_INTEGRATE) && ldi->append_buffer) {
kal_mem_cpy((void *)(ldi->append_buffer + (i* nvram_chksum_size)), (void *)(working_buffer + rec_size), nvram_chksum_size);
}
}
goto final;
}
if (rec_amount > 1) {
for (i = 1; i < max_rec_amount && i < rec_amount; i++) {
kal_mem_cpy(working_buffer + section_size * i, working_buffer, section_size);
//record integrated checksum
if((ldi->attr & NVRAM_ATTR_CHKSUM_INTEGRATE) && ldi->append_buffer) {
kal_mem_cpy((void *)(ldi->append_buffer + (i* nvram_chksum_size)), (void *)(working_buffer+rec_size), nvram_chksum_size);
}
}
}
#ifdef __NVRAM_CRYPT_TEST__
if (bWriteMsp == 1) {
kal_mem_cpy(&NVRAM_EF_MSP_TEST_W[NVRAM_MSP_TEST_LEN*2],working_buffer,NVRAM_MSP_TEST_LEN);
nvram_create_report_msp_file(KAL_TRUE);
}
#endif
if(NVRAM_IO_ERRNO_OK !=(result = get_lid_record_cache_offset(ldi, rec_index, section_size, &cache_offset))) {
nvram_fat_last_line = __LINE__;
goto final;
}
temp_rec_index = rec_index;
temp_cache_offset = cache_offset;
for (i = 0 ; i < rec_amount ; i += max_rec_amount) {
rec_in_block = (rec_amount - i) > max_rec_amount ? max_rec_amount: (rec_amount - i);
if (NVRAM_IO_ERRNO_OK != (result = nvram_write_data_to_cache(ldi, working_buffer, section_size * rec_in_block, temp_cache_offset))) {
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]%s->nvram_write_data_to_cache fail at %d,result=%d\r\n",__FUNCTION__,__LINE__,result);
result = NVRAM_DRV_INVALID_RECORD_ID;
nvram_fat_last_line = __LINE__;
goto final;
}
mask_dirty_bit_by_ltable_entry(ldi, temp_rec_index, rec_in_block);
mask_valid_bit_by_ltable_entry(ldi, temp_rec_index, rec_in_block);
temp_rec_index = temp_rec_index + rec_in_block;
temp_cache_offset = cache_offset + section_size * rec_in_block;
}
}
}
final:
if(result == NVRAM_IO_ERRNO_OK)
{
do
{
//write-back appdenix header info
if(ldi->attr & NVRAM_ATTR_CHKSUM_INTEGRATE)
{
if(ldi->append_offset == 0) {
ldi->append_offset = nvram_appendix_header_offset(ldi);
}
if(ldi->append_offset > 0) {
if(NVRAM_IO_ERRNO_OK != (result = get_lid_cache_base_address(ldi, &cache_offset))) {
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]%s->get_lid_cache_base_address fail at %d,result=%d\r\n",__FUNCTION__,__LINE__,result);
result = NVRAM_DRV_INVALID_RECORD_ID;
nvram_fat_last_line = __LINE__;
break;
}
cache_offset = cache_offset + (ldi->append_offset + NVRAM_LDI_APPENDIX_HEADER_SIZE + ((rec_index - 1) * nvram_chksum_size));
if (NVRAM_IO_ERRNO_OK != (result = nvram_write_data_to_cache(ldi, (kal_uint8*)ldi->append_buffer, (rec_amount * nvram_chksum_size), cache_offset))) {
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]%s->nvram_write_data_to_cache fail at %d,result=%d\r\n",__FUNCTION__,__LINE__,result);
result = NVRAM_DRV_INVALID_RECORD_ID;
nvram_fat_last_line = __LINE__;
break;
}
}
}
}while(0);
}
if(ldi->append_buffer) {
free_ctrl_buffer(ldi->append_buffer);
ldi->append_buffer = NULL;
}
if (working_buffer) {
free_ctrl_buffer(working_buffer);
working_buffer = NULL;
}
if (chksum)
{
free_ctrl_buffer(chksum);
chksum = NULL;
}
#if defined(__NVRAM_ACCESS_TIMEOUT_ASSERT__)
DclSGPT_Control(nvram_gpt_handle, SGPT_CMD_STOP, (DCL_CTRL_DATA_T*)NULL); //stop timer
#endif
if (NVRAM_IO_ERRNO_OK != result) {
nvram_fat_last_err = result;
MD_TRC_FUNC_NVRAM_DRV_FAT_THROW_EXCEPTION(nvram_fat_last_err, nvram_fat_last_line);
return result;
}
nvram_cache_enqueue(ldi, rec_index, rec_amount, openOption);
send_event_to_nvram_cache();
return NVRAM_DRV_OK;
}
/*****************************************************************************
* FUNCTION
* nvram_drv_fat_write_multiRec_to_cache
* DESCRIPTION
* write record(s) to FAT.
* PARAMETERS
* buffer [?]
* nvramname [?]
* section_number [IN]
* size [IN]
* initialize [IN] true for reset, false for normal write.
* RETURNS
* void
*****************************************************************************/
nvram_drv_status_enum nvram_drv_fat_write_multiRec_to_cache(
const kal_uint8 *buffer,
kal_uint16 rec_index,
kal_uint16 rec_amount,
kal_uint32 rec_size,
nvram_ltable_entry_struct *ldi)
{
/*----------------------------------------------------------------*/
/* Local Variables */
/*----------------------------------------------------------------*/
kal_uint32 openOption = FS_READ_WRITE | FS_OPEN_NO_DIR;
kal_uint32 remainLen = 0;
kal_uint8 *chksum = NULL;
kal_uint32 max_rec_amount;
kal_uint32 section_size;
kal_uint32 working_buffer_size;
kal_uint8 *working_buffer = NULL;
kal_int32 result = NVRAM_IO_ERRNO_OK;
kal_uint32 i;
kal_uint32 cache_offset = 0;
kal_uint32 temp_cache_offset = 0;
kal_uint16 temp_rec_index = rec_index;
kal_uint32 rec_in_block = 0;
nvram_ldi_ota_header ota_header;
kal_uint32 nvram_chksum_size = 0;
nvram_lid_chksum_info lid_chksum_info = {0};
#if defined(__NVRAM_ACCESS_TIMEOUT_ASSERT__)
SGPT_CTRL_START_T start;
#endif
/*----------------------------------------------------------------*/
/* Code Body */
/*----------------------------------------------------------------*/
/* NVRAM GPT timeout assert start timer */
#if defined(__NVRAM_ACCESS_TIMEOUT_ASSERT__)
start.u2Tick= NVRAM_WRITE_GPT_TIMEOUT;
start.pfCallback=nvram_gpt_timeout_callback;
start.vPara=NULL;
#endif
//nvram_util_take_mutex(g_nvram_fs_mutex);
#if defined(__NVRAM_ACCESS_TIMEOUT_ASSERT__)
DclSGPT_Control(nvram_gpt_handle, SGPT_CMD_START, (DCL_CTRL_DATA_T*)&start); //start timer
#endif
nvram_get_lid_chksum_algo_info(ldi, &lid_chksum_info, KAL_FALSE, KAL_FALSE);
nvram_chksum_size = lid_chksum_info.algo_info.chksum_algo_length;
/* set the attribute to empty before write data
sometime the files may be read only if the nvram lock is turn on
ex: software update when nvram lock is turned on
But it is not a good solution here, we should unlock it in io layer */
openOption |= FS_CREATE;
#if !defined(_NAND_FLASH_BOOTING_) && !defined(__FS_SYSDRV_ON_NAND__) && !defined(__EMMC_BOOTING__)
openOption |= FS_PROTECTION_MODE; /* boot from NAND and single bank NOR don't support this */
#endif
#if defined(__CCCIFS_SUPPORT__) && defined(__MTK_TARGET__)
if (ldi->attr & NVRAM_ATTR_COMMITTED) {
openOption |= FS_COMMITTED;
}
#endif
if (!nvram_util_has_file_created(ldi))
{
//prepare header data and write header
//nvram_prepare_data_header(ldi, ldi_hd_buffer);
if (KAL_FALSE == nvram_write_data_header(ldi, LDI_HEADER_ALL_SECTION))
{
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]%s->nvram_write_data_header fail at %d,result=%d\r\n",__FUNCTION__,__LINE__,result);
result = NVRAM_ERROR_LOC_NVCACHE_ERRNO_WRITE_HEADER_FAIL;
nvram_fat_last_line = __LINE__;
goto final;
}
}
//Get appdenix header info
if(ldi->attr & NVRAM_ATTR_CHKSUM_INTEGRATE) {
ldi->append_buffer = get_ctrl_buffer(rec_amount * nvram_chksum_size);
}
#ifdef __NVRAM_BIND_TO_CHIP_CIPHER__
if ((ldi->attr & NVRAM_ATTR_MSP)||(ldi->attr & NVRAM_ATTR_CONFIDENTIAL)) {
/* 16 byte alignment */
remainLen = NVRAM_MSP_ALIGNMENT_REMAINDER(rec_size + nvram_chksum_size);
}
#else
if (ldi->attr & NVRAM_ATTR_CONFIDENTIAL) {
/* 16 byte alignment */
remainLen = NVRAM_MSP_ALIGNMENT_REMAINDER(rec_size + nvram_chksum_size);
}
#endif
section_size = rec_size + nvram_chksum_size + remainLen;
working_buffer_size = section_size * rec_amount;
if (working_buffer_size > MAX_NVRAM_RECORD_SIZE) {
working_buffer_size = MAX_NVRAM_RECORD_SIZE;
}
working_buffer = (kal_uint8*) get_ctrl_buffer(working_buffer_size);
chksum = (kal_uint8*) get_ctrl_buffer(nvram_chksum_size);
if(NVRAM_IO_ERRNO_OK !=(result = get_lid_record_cache_offset(ldi, rec_index, section_size, &cache_offset)))
{
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]%s->get_lid_record_cache_offset fail at %d,result=%d\r\n",__FUNCTION__,__LINE__,result);
result = NVRAM_DRV_INVALID_RECORD_ID;
nvram_fat_last_line = __LINE__;
goto final;
}
temp_cache_offset = cache_offset;
if (!(ldi->attr & NVRAM_ATTR_MSP) && !(ldi->attr & NVRAM_ATTR_CONFIDENTIAL) &&
buffer != NVRAM_EF_ZERO_DEFAULT && buffer != NVRAM_EF_FF_DEFAULT)
{
for(i = 0; i < rec_amount; i++)
{
if (ldi->attr & NVRAM_ATTR_MULTI_DEFAULT)
{
//rec_index start from 1
kal_mem_set(chksum, 0, nvram_chksum_size);
nvram_util_caculate_checksum(ldi, buffer + (i+rec_index-1)*rec_size, rec_size,chksum);
kal_mem_cpy(working_buffer + i*(rec_size + nvram_chksum_size), buffer + (i+rec_index-1)*rec_size, rec_size);
kal_mem_cpy(working_buffer + i*(rec_size + nvram_chksum_size)+rec_size, chksum, nvram_chksum_size);
}
else
{
if (i==0)
{
kal_mem_set(chksum, 0, nvram_chksum_size);
nvram_util_caculate_checksum(ldi, buffer, rec_size,chksum);
}
kal_mem_cpy(working_buffer + i*(rec_size + nvram_chksum_size), buffer, rec_size);
kal_mem_cpy(working_buffer + i*(rec_size + nvram_chksum_size)+rec_size, chksum, nvram_chksum_size);
}
//record integrated checksum
if((ldi->attr & NVRAM_ATTR_CHKSUM_INTEGRATE) && ldi->append_buffer) {
kal_mem_cpy((void *)(ldi->append_buffer + (i* nvram_chksum_size)), (void *)chksum, nvram_chksum_size);
}
if (i == (rec_amount - 1))
{
if (NVRAM_IO_ERRNO_OK != (result = nvram_write_data_to_cache(ldi, working_buffer, section_size * rec_amount, cache_offset)))
{
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]%s->nvram_write_data_to_cache fail at %d,result=%d\r\n",__FUNCTION__,__LINE__,result);
result = NVRAM_DRV_INVALID_RECORD_ID;
nvram_fat_last_line = __LINE__;
goto final;
}
mask_dirty_bit_by_ltable_entry(ldi, rec_index, rec_amount);
mask_valid_bit_by_ltable_entry(ldi, rec_index, rec_amount);
}
}
goto final;
}
rec_in_block = 0;
max_rec_amount = working_buffer_size / section_size;
for (i = 0; i < rec_amount; i ++)
{
nvram_drv_fat_prepare_data(working_buffer + rec_in_block * section_size, buffer, (i+rec_index-1) * rec_size, rec_size);
kal_mem_set(chksum, 0, nvram_chksum_size);
nvram_util_caculate_checksum(ldi, working_buffer + rec_in_block * section_size, rec_size, chksum);
kal_mem_cpy(working_buffer + rec_in_block * section_size + rec_size, chksum, nvram_chksum_size);
//record integrated checksum
if((ldi->attr & NVRAM_ATTR_CHKSUM_INTEGRATE) && ldi->append_buffer) {
kal_mem_cpy((void *)(ldi->append_buffer + (i* nvram_chksum_size)), (void *)chksum, nvram_chksum_size);
}
if (remainLen)
{
kal_mem_set(working_buffer + rec_in_block * section_size + rec_size + nvram_chksum_size , 0x00, remainLen);
}
if (ldi->attr & NVRAM_ATTR_CONFIDENTIAL)
{
//custom_nvram_encrypt(nvram_ptr->secret_key, working_buffer + rec_in_block * section_size, rec_size, rec_size);
nvram_AES_encrypt(working_buffer + rec_in_block * section_size, section_size);
}
#ifdef __NVRAM_BIND_TO_CHIP_CIPHER__
if (ldi->attr & NVRAM_ATTR_MSP)
{
/* this solution is only for work arround */
#if (defined(__SMART_PHONE_MODEM__) || defined(__CCCIFS_SUPPORT__))
kal_uint8 *working_buffer2 = (kal_uint8*) get_ctrl_buffer(section_size);
kal_uint8 *working_buffer3 = (kal_uint8*) get_ctrl_buffer(section_size);
//copy the original data from working_buffer to working_buffer2
memcpy(working_buffer2, working_buffer + rec_in_block * section_size, section_size);
do
{
nvram_trace_to_file(__LINE__, 999, 0, 0, 0, 0);
nvram_trace_to_file(nvram_ptr->secret_key[0], nvram_ptr->secret_key[1], nvram_ptr->secret_key[2], nvram_ptr->secret_key[3], 0, 0);
nvram_trace_to_file(working_buffer[rec_in_block*section_size], working_buffer[rec_in_block*section_size + 1], working_buffer[rec_in_block*section_size + 2], working_buffer[rec_in_block*section_size + 3], 0, 0);
//encrypt working_buffer
SST_Secure_Algo(NVRAM_MSP_ENCRYPT, (kal_uint32)working_buffer + rec_in_block * section_size, section_size, nvram_ptr->secret_key, working_buffer + rec_in_block * section_size);
nvram_trace_to_file(working_buffer[rec_in_block*section_size], working_buffer[rec_in_block*section_size + 1], working_buffer[rec_in_block*section_size + 2], working_buffer[rec_in_block*section_size + 3], 0, 0);
//copy the encrypted data from working_buffer to working_buffer3
memcpy(working_buffer3, working_buffer + rec_in_block * section_size, section_size);
//decrypt the working_buffer3
SST_Secure_Algo(NVRAM_MSP_DECRYPT, (kal_uint32)working_buffer3, section_size, nvram_ptr->secret_key, working_buffer3);
//compare the data between the working_buffer2 & working_buffer3
if (memcmp(working_buffer2, working_buffer3, section_size) == 0)
{
//encrypt PASS
break;
}
else
{
//encrypt FAIL, try again, WTF
memcpy(working_buffer + rec_in_block * section_size, working_buffer2, section_size);
}
}while(1);
free_ctrl_buffer(working_buffer2);
free_ctrl_buffer(working_buffer3);
working_buffer2 = NULL;
working_buffer3 = NULL;
#else
SST_Secure_Algo(NVRAM_MSP_ENCRYPT, (kal_uint32)working_buffer + rec_in_block * section_size, section_size, nvram_ptr->secret_key, working_buffer + rec_in_block * section_size);
#endif
}
#endif
/* if this is not multi default, no need to prepare data anymore */
if (!(ldi->attr & NVRAM_ATTR_MULTI_DEFAULT))
{
break;
}
rec_in_block ++;
if (rec_in_block == max_rec_amount || i == rec_amount - 1)
{
result = nvram_write_data_to_cache(ldi, working_buffer, section_size * rec_in_block, temp_cache_offset);
if (NVRAM_IO_ERRNO_OK != result)
{
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]%s->vram_write_data_to_cache fail at %d,result=%d\r\n",__FUNCTION__,__LINE__,result);
result = NVRAM_DRV_INVALID_RECORD_ID;
nvram_fat_last_line = __LINE__;
goto final;
}
mask_dirty_bit_by_ltable_entry(ldi, temp_rec_index, rec_in_block);
mask_valid_bit_by_ltable_entry(ldi, temp_rec_index, rec_in_block);
temp_cache_offset += section_size * rec_in_block;
temp_rec_index += rec_in_block;
rec_in_block = 0;
}
}
/* special handling for not multi default */
if (!(ldi->attr & NVRAM_ATTR_MULTI_DEFAULT))
{
for (i = 0; i < rec_amount; i++)
{
//record integrated checksum
if((ldi->attr & NVRAM_ATTR_CHKSUM_INTEGRATE) && ldi->append_buffer) {
kal_mem_cpy((void *)(ldi->append_buffer + (i* nvram_chksum_size)), (void *)(working_buffer+rec_size), nvram_chksum_size);
}
temp_cache_offset = cache_offset + section_size * i;
if (NVRAM_IO_ERRNO_OK != (result = nvram_write_data_to_cache(ldi, working_buffer, section_size, temp_cache_offset)))
{
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]%s->nvram_write_data_to_cache fail at %d,result=%d\r\n",__FUNCTION__,__LINE__,result);
result = NVRAM_DRV_INVALID_RECORD_ID;
nvram_fat_last_line = __LINE__;
goto final;
}
mask_dirty_bit_by_ltable_entry(ldi, rec_index+i, 1);
mask_valid_bit_by_ltable_entry(ldi, rec_index+i, 1);
}
}
final:
if(result == NVRAM_IO_ERRNO_OK)
{
do
{
//write-back appdenix header info
if(ldi->attr & NVRAM_ATTR_CHKSUM_INTEGRATE)
{
//Write appendix header
nvram_prepare_appendix_header(NVRAM_APPEND_TYPE_CHKSUM, (nvram_ldi_appendix_header*)(&ota_header), ldi, NVRAM_LDI_APPENDIX_HEADER_SIZE);
if(NVRAM_IO_ERRNO_OK != (result = get_lid_cache_base_address(ldi, &cache_offset)))
{
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]%s->get_lid_cache_base_address fail at %d,result=%d\r\n",__FUNCTION__,__LINE__,result);
result = NVRAM_DRV_INVALID_RECORD_ID;
nvram_fat_last_line = __LINE__;
break;
}
if (NVRAM_IO_ERRNO_OK != (result = nvram_write_data_to_cache(ldi, &ota_header, NVRAM_LDI_APPENDIX_HEADER_SIZE, (cache_offset + ldi->append_offset))))
{
kal_prompt_trace(MOD_NVRAM, "NVRAM appendix header write fail:0x%x\n\r", result);
kal_prompt_trace(MOD_NVRAM, "category:0x%x, attr:0x%x\n\r", ldi->category, ldi->attr);
kal_prompt_trace(MOD_NVRAM, "fileprefix:%s, fileverno:%s\n\r", ldi->fileprefix, ldi->fileverno);
kal_prompt_trace(MOD_NVRAM, "cache_offset:%d\n\r", cache_offset);
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"NVRAM appendix header write fail:0x%x\r\n", result);
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"category:0x%08X, attr:0x%08X\r\n", ldi->category, ldi->attr);
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"fileprefix:%s, fileverno:%s\r\n", ldi->fileprefix, ldi->fileverno);
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"cache_offset:%d\r\n", cache_offset);
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]%s->nvram_write_data_to_cache fail at %d,result=%d\r\n",__FUNCTION__,__LINE__,result);
if(NVRAM_IS_ATTR_FAULT_ASSERT(ldi->attr))
{
if(ldi->append_buffer)
{
free_ctrl_buffer(ldi->append_buffer);
ldi->append_buffer = NULL;
}
if (working_buffer)
{
free_ctrl_buffer(working_buffer);
working_buffer = NULL;
}
NVRAM_EXT_ASSERT(KAL_FALSE, (kal_uint32)result, NVRAM_ERROR_LOC_NVCACHE_ERRNO_WRITE_HEADER_FAIL, ldi->LID);
}
}
//write-back appdenix header info
if(ldi->append_offset == 0)
{
ldi->append_offset = nvram_appendix_header_offset(ldi);
}
if(ldi->append_offset > 0)
{
cache_offset = cache_offset + (ldi->append_offset + NVRAM_LDI_APPENDIX_HEADER_SIZE + ((rec_index - 1) * nvram_chksum_size));
if (NVRAM_IO_ERRNO_OK != (result = nvram_write_data_to_cache(ldi, (kal_uint8*)ldi->append_buffer, (rec_amount * nvram_chksum_size), cache_offset)))
{
NVRAM_DEBUG_DUMP(NVRAM_CRITICAL_DUMP,"[Error]%s->nvram_write_data_to_cache fail at %d,result=%d\r\n",__FUNCTION__,__LINE__,result);
result = NVRAM_DRV_INVALID_RECORD_ID;
nvram_fat_last_line = __LINE__;
break;
}
}
}
}while(0);
}
if(ldi->append_buffer)
{
free_ctrl_buffer(ldi->append_buffer);
ldi->append_buffer = NULL;
}
if (working_buffer)
{
free_ctrl_buffer(working_buffer);
working_buffer = NULL;
}
if (chksum)
{
free_ctrl_buffer(chksum);
chksum = NULL;
}
#if defined(__NVRAM_ACCESS_TIMEOUT_ASSERT__)
DclSGPT_Control(nvram_gpt_handle, SGPT_CMD_STOP, (DCL_CTRL_DATA_T*)NULL); //stop timer
#endif
if (NVRAM_IO_ERRNO_OK != result) {
nvram_fat_last_err = result;
MD_TRC_FUNC_NVRAM_DRV_FAT_THROW_EXCEPTION(nvram_fat_last_err, nvram_fat_last_line);
return result;
}
nvram_cache_enqueue(ldi, rec_index, rec_amount, openOption);
send_event_to_nvram_cache();
return NVRAM_DRV_OK;
}
#endif