/*****************************************************************************
Function   : NV_Mkdir
Description: make a directory
Input      : VOS_CHAR *pcDirName -> Directory name
Return     : OK, or ERROR if the directory cannot be created
Other      :
*****************************************************************************/
VOS_INT32 NV_Mkdir(VOS_CHAR *pcDirName)
{
    VOS_INT32 ulRslt;

    ulRslt = DRV_FILE_MKDIR(pcDirName);

    if(VOS_OK != ulRslt)
    {
        NV_Printf("Make Dir %s fail.\r\n", pcDirName);
    }

    return ulRslt;
}
/*****************************************************************************
Function   : NV_File_Read
Description: Read data into an array
Input      : VOS_VOID *pBuf -> Where to copy data
             VOS_UINT32 ulSize -> Element size
             VOS_UINT32 ulCount -> No. of elements
             FILE *Fp -> File position
Return     : The number of elements successfully read
Other      :
*****************************************************************************/
VOS_INT32 NV_File_Read(VOS_VOID *pBuf,VOS_UINT32 ulSize,VOS_UINT32 ulCount,FILE *Fp)
{
    VOS_INT                             lRslt;

    lRslt = DRV_FILE_READ(pBuf,ulSize,ulCount,Fp);

    if ( (VOS_UINT32)lRslt != ulCount )
    {
        NV_Printf("NV:Read File fail.\r\n");
    }

    return lRslt;
}
/*****************************************************************************
Function   : NV_File_Tell
Description: Return the current value of the file position indicator
Input      : FILE *Fp -> File position
Return     : The current value of the file position indicator
Other      :
*****************************************************************************/
VOS_INT32 NV_File_Tell(FILE *Fp)
{
    VOS_INT32 lFileSize = VOS_ERROR;

    lFileSize = DRV_FILE_TELL(Fp);

    if ( VOS_ERROR == lFileSize)
    {
        NV_Printf("NV:Tell File Size fail.\r\n");
    }

    return lFileSize;
}
/*****************************************************************************
Function   : NV_File_Seek
Description: Set the file position indicator
Input      : FILE *Fp -> File position
             VOS_INT32 lOffset -> Offset from lWhence
             VOS_INT32 lWhence -> Position to offset from
Return     : OK or ERR
Other      :
*****************************************************************************/
VOS_INT32 NV_File_Seek( FILE *Fp,VOS_INT32 lOffset,VOS_INT32 lWhence)
{
    VOS_INT32 ulRslt = VOS_ERR;

    ulRslt = DRV_FILE_LSEEK(Fp,lOffset,lWhence);

    if ( VOS_OK != ulRslt )
    {
        NV_Printf("NV:Seek File fail.\r\n");
    }

    return ulRslt;
}
/*****************************************************************************
Function   : NV_File_Close
Description: Close File
Input      : FILE *Fp -> File ptr
Return     : OK or ERR
Other      :
*****************************************************************************/
VOS_INT32 NV_File_Close( FILE *Fp )
{
    VOS_INT32 lRslt = VOS_ERR;

    lRslt = DRV_FILE_CLOSE(Fp);

    if ( VOS_OK != lRslt )
    {
        NV_Printf("NV:Close File fail.\r\n");
    }

    return lRslt;
}
/*****************************************************************************
Function   : NV_File_Open
Description: Open a file specified by name
Input      : VOS_CHAR *pcFileName -> Name of File
             VOS_CHAR *pcAccessMode -> Open Mode
Return     : FILE *
Other      :
*****************************************************************************/
FILE *NV_File_Open( VOS_CHAR *pcFileName, VOS_CHAR *pcAccessMode )
{
    FILE *fp;

    fp = DRV_FILE_OPEN(pcFileName,pcAccessMode);

    if ( VOS_NULL_PTR == fp )
    {
        NV_Printf("Open File %s fail.\r\n", pcFileName);
    }

    return fp;
}
/*****************************************************************************
Function   : NV_File_Write
Description: Write from a specified array
Input      : VOS_VOID *pBuf -> where to copy from
             VOS_UINT32 ulSize -> Element size
             VOS_UINT32 ulCount -> No. of elements
             FILE *Fp -> File position
Return     : The number of elements successfully written
Other      :
*****************************************************************************/
VOS_INT32 NV_File_Write(VOS_VOID *pBuf,VOS_UINT32 ulSize,VOS_UINT32 ulCount,FILE *Fp)
{
    VOS_INT32                             lRslt;

    lRslt = DRV_FILE_WRITE(pBuf,ulSize,ulCount,Fp);

    if ( lRslt != ulCount )
    {
        NV_Printf("NV:Write File fail.\r\n");
    }

    return lRslt;

}
/*****************************************************************************
Function   : NV_File_Remove
Description: remove a file
Input      : VOS_CHAR *pcFileName -> File name
Return     : OK, or ERROR
Other      :
*****************************************************************************/
VOS_INT32 NV_File_Remove(VOS_CHAR *pcDir, VOS_CHAR *pcFile)
{
    VOS_INT32                           lRslt;
    VOS_CHAR                            acFilePath[MAX_PATH] = {0};

    strncpy(acFilePath, pcDir, (MAX_PATH - 1));

    if (VOS_NULL_PTR != pcFile)
    {
        strncat(acFilePath, pcFile, (MAX_PATH - VOS_StrLen(acFilePath) - 1));
    }

    lRslt = DRV_FILE_RMFILE(acFilePath);

    if(VOS_OK != lRslt)
    {
        NV_Printf("Remove File %s fail.\r\n", acFilePath);
    }

    return lRslt;
}
VOS_UINT32 NV_Init(VOS_VOID)
{
    VOS_UINT8           aucMagicNum[NV_MAGIC_NUM_LEN];
    VOS_UINT8           aucTemp[NV_MAGIC_NUM_LEN];
    BSP_DDR_SECT_INFO_S   stNVMemInfo;
    BSP_DDR_SECT_QUERY_S  stNVMemQuery;

    g_ulNVInitStartSlice = mdrv_timer_get_normal_timestamp();

    /*lint -e534*/
    VOS_MemSet(g_astNvFileHandle, 0, sizeof(g_astNvFileHandle));

    vos_printf("\r\n---------------------NV_Init Start-----------------------------\r\n");

    VOS_MemSet(aucMagicNum, NV_MAGIC_NUM, NV_MAGIC_NUM_LEN);
    /*lint +e534*/

    stNVMemQuery.enSectType = BSP_DDR_SECT_TYPE_NV;
    stNVMemQuery.ulSectSize = NV_BACKUP_BUFFER_SIZE;
    stNVMemQuery.enSectAttr = BSP_DDR_SECT_ATTR_NONCACHEABLE;

    if(MDRV_OK != mdrv_get_fix_ddr_addr(&stNVMemQuery, &stNVMemInfo))
    {
        /*lint -e534*/
        vos_printf("\r\nNV_Init: Acpu mdrv_get_fix_ddr_addr Failed\r\n");
        /*lint +e534*/

        mdrv_om_system_error(NV_INIT_ERROR, NV_GET_DRV_FIX_DDR_ADDR_FAIL,
                              0, (VOS_CHAR *)VOS_NULL_PTR, 0);

        return NV_INIT_FAIL;
    }

    g_ulNVMemAddr = (VOS_UINT_PTR)mdrv_phy_to_virt(MEM_DDR_MODE, stNVMemInfo.pSectPhysAddr);     /*上层使用虚地址*/

    /* 创建NV写操作保护信号量 */
    if(VOS_OK != VOS_SmMCreate("NV", VOS_SEMA4_PRIOR | VOS_SEMA4_INVERSION_SAFE,
                                &g_ulNVWriteSem))
    {
        return VOS_ERR;
    }

    if(MDRV_OK != mdrv_ipc_sem_create(IPC_SEM_NVIM))
    {
        NV_Printf("NV_Init: Acpu mdrv_ipc_sem_create Failed\r\n");

        return NV_INIT_FAIL;
    }

    /* 等待C 核NV初始化完毕 */
    (VOS_VOID)VOS_SmP(g_ulNVInitSem, 0);

    NV_MEMCPY(aucTemp, (VOS_VOID*)NV_MAGICNUM_ADDR, NV_MAGIC_NUM_LEN);  /*从share memory读取标志字节*/

    if(VOS_OK != VOS_MemCmp(aucMagicNum, aucTemp, NV_MAGIC_NUM_LEN))    /*Ccpu的Nv项已经初始化成功*/
    {
        /* 单板复位 */
        mdrv_om_system_error(NV_INIT_ERROR, NV_GET_CCORE_MAGIC_NUM_FAIL,
                             0, (VOS_CHAR *)VOS_NULL_PTR, 0);
    }

    NV_BuildGlobalVar();

    /*lint -e534*/
    vos_printf("\r\n---------------------NV_Init End-----------------------------\r\n");
    /*lint +e534*/

    g_ulNVInitEndSlice = mdrv_timer_get_normal_timestamp();

    DRV_MSP_PROC_REG(OM_READ_NV_PROC, (BSP_MspProc)NV_ReadEx);

    /* 检测是否开启NV写操作记录跟踪 */
    if (NV_OK != NV_ReadEx(MODEM_ID_0, en_NV_Item_Write_Slice_Record_Flag, (VOS_VOID*)&g_ulRecordNvFlag, sizeof(g_ulRecordNvFlag)))
    {
        g_ulRecordNvFlag = 0;
    }

    return NV_OK;
}
/*****************************************************************************
Function   : NV_DeleteFileBySuffix
Description: Delete files by file's suffix name.
Input      : pcDirName - the file's directory.
Return     : VOID
Other      :
*****************************************************************************/
VOS_VOID NV_DeleteFilesBySuffix(VOS_CHAR *pcDirPath, VOS_CHAR *pcSuffixName)
{
    DRV_DIR_STRU                       *pstTmpDir;
    DRV_DIRENT_STRU                    *pstTmpDirent;
    VOS_UINT32                          ulNameLen;
    VOS_CHAR                            acSuffixSrc[NV_XML_SUFFIX_STR_SIZE];
    VOS_UINT32                          i;
    VOS_UINT32                          ulLoopNum = 0;
    VOS_UINT32                          ulFileNum = 0;

    pstTmpDir = DRV_FILE_OPENDIR(pcDirPath);

    if (VOS_NULL_PTR == pstTmpDir)
    {
        NV_Printf("NV_DeleteFilesBySuffix, DRV_FILE_OPENDIR %s fail.\r\n", pcDirPath);

        return;
    }

    do
    {
        pstTmpDirent = DRV_FILE_READDIR(pstTmpDir);

        /* readdir's return value is zero, so the loop should be over. */
        if (VOS_NULL_PTR != pstTmpDirent)
        {
            /* ulNumLen includes the ending of string. */
            ulNameLen = VOS_StrLen(pstTmpDirent->d_name) + 1;

            if (NV_XML_SUFFIX_STR_SIZE < ulNameLen)
            {
                for (i = 0; i < NV_XML_SUFFIX_STR_SIZE; i++)
                {
                    acSuffixSrc[i] = (VOS_CHAR)tolower(pstTmpDirent->d_name[ulNameLen - (NV_XML_SUFFIX_STR_SIZE - i)]);
                }

                if (VOS_OK == VOS_StrCmp(acSuffixSrc, pcSuffixName))
                {
                    NV_File_Remove(pcDirPath, pstTmpDirent->d_name);
                    ulFileNum++;
                }
            }
        }

        /* Avoid dead loop.*/
        ulLoopNum++;
    }while ((VOS_NULL_PTR != pstTmpDirent) && (ulLoopNum < NV_XML_FILE_MAX_NUM));

    if (VOS_OK != DRV_FILE_CLOSEDIR(pstTmpDir))
    {
        NV_Printf("NV_DeleteFilesBySuffix, DRV_FILE_CLOSEDIR fail.\r\n");
    }

    if (NV_XML_FILE_MAX_NUM == ulLoopNum)
    {
        NV_Printf("NV_DeleteFilesBySuffix, File system crashed.\r\n");
    }

    /* Record the number of deleted files. */
    if (0 != ulFileNum)
    {
        NV_Printf("NV_DeleteFilesBySuffix, the num of deleted files: %d.\r\n", ulFileNum);
    }

    return;
}