/*
* @filename PFM_RemoteUpdate.c
* @brief Platform Function Module:远程部署、重启
* @details
* 
* @author GT-BU
* @date 2023.02.07
* @version V1.0
* @copyright TCT
* @par 修改日志
* <table>
* <tr><th>Date        <th>Version  <th>Author     <th>Description
* <tr><td>2023.02.07  <td>V1.0     <td>GT-BU      <td>创建初始版本
* </table>
*/
#include "PFM_RemoteUpdate.h"
#include "PFM_InputOutput.h"
#include "SFM_Prtcl.h"
#include "SFM_2x2.h"
#include "SFM_2oo2.h"
#include "CM_Memory.h"
#include "CM_CRC32.h"
#include "CM_MD5.h"
#include "CM_Time.h"
#include "CM_Convert.h"
#include "PFM_Cfg.h"
#include "PFM_Log.h"
#include "PFM_SelfCheck.h"
#include "DFM_DRV.h"
#include "MSCP_APP_API.h"
#include "PFM_ControlFlowCheck.h"
#include "DFM_Time.h"

#define WAIT_TIME_2S   (2000u/g_PFM_Cfg.CYC_TIME + 1u)
#define WAIT_TIME_10S  (10000u/g_PFM_Cfg.CYC_TIME + 1u)
#define WAIT_TIME_120S  (120000u/g_PFM_Cfg.CYC_TIME + 1u)
CM_UINT16 g_Maintenance_Id = 0x00u;/* 维护终端内网id */
CM_UINT8 g_RemoteUpdate_State = 0x00u;/* 远程部署过程状态 */

ENUM_BOARD_STATE_T g_boardState = ENUM_BOARDSTATE_ERROR;
/*应用设置临时状态*/
ENUM_BOARD_STATE_T g_AppSetboardState = ENUM_BOARDSTATE_ERROR;
static CM_UINT32 s_packTimer = 0u; /**< 请求命令时间戳 */
static CM_UINT32 s_packFirstSendTimer = 0u; /**< 第一次回复重启确认的周期号 */
static CM_UINT32 s_packFirstRecvTimer = 0u; /**< 收到aid第一次回复重启确认的周期号 */
static CM_UINT8 reboottype = 0u;/**< 重启请求命令  0x55:未更新重启  0xaa:升级重启  0xd1~d7:硬重启 */
extern CM_UINT32 g_MSCP_SysCount; /**< 系统周期号 */
static CM_UINT8 s_countres = 0u;/**重启确认报文回复次数计数 */
static CM_UINT8 packAccredit = 2u; /**授权状态 (当变量置为0或者1,则需要处理远程重启请求报文)*/
static CM_UINT8 reasonAuthorization = 0u; /*授权原因*/
static CM_UINT8 s_HardReboottype = 0u;/**<0xd1~d7:硬重启 */
static CM_UINT8 s_packHardAccredit = 2u; /**硬重启授权状态 (当变量置为0或者1,则需要处理远程重启请求报文)*/
static CM_UINT8 s_reasonHardAuthorization = 0u; /*硬重启授权原因*/

static CM_UINT8 s_packSwitchAccredit = 2u; /**硬重启授权状态 (当变量置为0或者1,则需要处理远程重启请求报文)*/
static CM_UINT8 s_switchAuthorization = 0u; /*硬重启授权原因*/

static CM_UINT32 s_WaitTime = 0u;	/* 继电器输出等待时间 */
static CM_UINT8 s_FaultRebootCut= 0u;/*故障重启次数*/

static CM_UINT8 g_iostate = 0u;
static CM_UINT8 s_switchRmFlag = 0xaa;
CM_UINT8 s_switch2xFlag = 0xaa;

extern CM_INT32 g_PFM_Check;
/** 需应用注册的版本号 */
extern STRU_APP_VERSON g_App_Verson;
/** 识别AB系通信需要计算的板卡通信状态(对系)  */
CM_UINT8 PFM_HardWareBoot_CheckSelf_Com(ENUM_BOARD_TYPE_T type);
/** 文件更新信息结构 */
typedef struct
{
	CM_UINT16 FileNameLen;		  /**< 文件名长度 */
	CM_UINT8 FileName[FILE_NAME_MAX_LEN];	/**< 文件名 */
	CM_UINT8  md5[CM_MD5_SIZE_BYTE];/*- 存储初始比较时的校验码*/
}STRU_FILE_UPDATE_CTRL_T;

static STRU_FILE_UPDATE_CTRL_T s_FileUpdateSucess[FILE_MAX_QUANTITY];/*- 升级成功的文件*/
static CM_UINT8 Filesum_check = 0u; /**< 已验证文件数量总和 */
static CM_UINT8 Filesum_check_cur = 0u; /**< 本次已验证文件数量 */
/*-  文件更新请求命令确认处理 */
ENUM_CM_RETURN PFM_FileUpdate_Response(IN CM_UINT32 TimeStamp,IN CM_UINT8 State,IN CM_UINT8 Reason);

/*- 文件上传完成验证命令确认处理 */
ENUM_CM_RETURN PFM_FileVerity_Response(IN CM_UINT32 TimeStamp,IN STRU_FILE_UPDATE_CTRL_T FileUpdateMsg[],IN CM_UINT8 Quantity);

/*- 远程重启命令处理 */
static void PFM_DataReastart(void);

/*- 远程重启命令接收处理 */
static CM_UINT8 PFM_DataReastart_Recv(void);

/*- 远程重启命令发送处理 */
static void PFM_DataReastart_Send(void);

/*- 远程重启命令二次确认发送处理 */
static void PFM_DataReastart_SendTwo(void);

/*- 删除文件 */
static void PFM_RM_File(IN CM_UINT8  pathname[]);

/*- 远程硬件重启命令接收处理 */
static void PFM_Data_HardWareReastart(CM_UINT8* mData,CM_UINT32 dataOffset,CM_UINT16 packLen,CM_UINT8 packType);

/*- 远程切系命令接收处理  */
static void PFM_Data_RemoteSwitch(CM_UINT8* mData,CM_UINT32 dataOffset,CM_UINT16 packLen,CM_UINT8 packType);

/*- 远程切系确认帧组包发送 */
static void PFM_RemoteSwitch_Send(CM_UINT8 type,CM_UINT32 rcv_packTime,CM_UINT8 accredit,CM_UINT8 reason);

/*- 硬件重启确认帧组包发送 */
static void PFM_HardWareReastart_Send(CM_UINT8 type,CM_UINT32 rcv_packTime,CM_UINT8 accredit,CM_UINT8 reason);

/*- 继电器检测 */
static ENUM_HARDWARE_BOOT_SELFCHECK_T PFM_Realy_Check(ENUM_HARDWARE_BOOT_SELFCHECK_T s_selfcheck_state,CM_UINT32 s_OutPutTime, CM_UINT8 comResult);
/**
* @brief 获取故障重启次数
* @return 重启次数 取值范围:0~0xff
*/
CM_UINT8 RM_Get_FaultRbootCut(void)
{
	return s_FaultRebootCut;
}

/**
* @brief 重置故障重启次数
* @param Cut 重启次数 取值范围:0~0xff
* @return 无
*/
void RM_Reset_FaultRbootCut(CM_UINT8 Cut)
{
	/*- 设置重启参数 */
	s_FaultRebootCut = Cut;
}
/**
* @brief 检测SFTP服务是否开启
* @return 处理结果
* - ENUM_CM_TRUE 成功
* - ENUM_CM_FALSE 失败
*/
ENUM_CM_RETURN PFM_SftpIsOk(void )
{
	ENUM_CM_RETURN rt = ENUM_CM_FALSE; /* 函数返回值 */
	FILE *fp=NULL;
	CM_CHAR StrLine[128u] = {0}; /*每行最大读取的字符数*/
	CM_INT32 ret = -1; /*函数返回值*/
	/* 通过popen函数，管道方式执行命令 */
	fp = popen("pidin | grep sftp","r");
	if (NULL != fp)
	{
		/* 读取一行, */
		(void)fgets(StrLine,128,fp);
		if (0u != strlen(StrLine))
		{
			rt = ENUM_CM_TRUE;
		}
		else
		{
			rt = ENUM_CM_FALSE;
		}
		
		/* 关闭文件指针 */
		ret = pclose(fp);
		if(-1 == ret)
	    {
	        perror("pclose failed");
	        rt = ENUM_CM_FALSE;
	    }
	    else
	    {
			
	    }
	}
	else
	{
		perror("PFM_SftpIsOk popen call failed");
		(void)printf("popen errno=%d,%s\n",errno,strerror(errno));
		rt = ENUM_CM_FALSE;
	}
	return rt;
}

/**
* @brief 通过路径查找文件
* @param pathname[] 查找的绝对路径文件名
* @param len 查找的文件名长度
* @return 处理结果
* - ENUM_CM_TRUE 成功
* - ENUM_CM_FALSE 失败
*/
ENUM_CM_RETURN PFM_FindFileByPath(IN CM_UINT8  pathname[], IN CM_UINT8 len)
{
	ENUM_CM_RETURN rt = ENUM_CM_FALSE; /* 函数返回值 */
	CM_INT8 ret = -1;/* 临时函数返回值 */
	CM_UINT8 pathnametmp[FILE_NAME_MAX_LEN]={0u};
	
	(void)strcat(pathnametmp,g_RMUP_Cfg.Start_Path);
	(void)strcat(pathnametmp,"/Backup/");
	(void)strcat(pathnametmp,pathname);
	ret = access(pathnametmp, 0);
	if (0 == ret)
	{
		rt = ENUM_CM_TRUE;
	}
	else
	{
		MSCP_LOG_MSG("PFM_FindFileByPath filename %s error!!!\n",pathnametmp);
	}
	return rt;
}

/**
* @brief 删除文件
* @param pathname[] 查找的绝对路径文件名
* @return 处理结果
* - ENUM_CM_TRUE 成功
* - ENUM_CM_FALSE 失败
*/
static void PFM_RM_File(IN CM_UINT8  pathname[])
{
	CM_UINT8 pathnametmp[FILE_NAME_MAX_LEN]={0u};
	/*- 入参防空*/
	CM_ASSERT_MAINTAIN(pathname != NULL);
	(void)strcat(pathnametmp,g_RMUP_Cfg.Start_Path);
	(void)strcat(pathnametmp,"/Backup/");
	(void)strcat(pathnametmp,pathname);
	MSCP_LOG_MSG("%s\r\n",pathnametmp);

    (void)remove(pathnametmp);
}

/**
* @brief 计算MD5值
* @param pathname[] 查找的绝对路径文件名
* @param len 查找的文件名长度
* @return 处理结果
* - ENUM_CM_TRUE 成功
* - ENUM_CM_FALSE 失败
*/
ENUM_CM_RETURN PFM_MD5_Calc(IN CM_UINT8  pathname[], IN CM_UINT16 len,OUT CM_UINT8 Md5buf[])
{
	ENUM_CM_RETURN rt = ENUM_CM_FALSE; /* 函数返回值 */

	FILE *pfile = NULL;      /* 文件指针 */
	CM_UINT64 fileSize = 0u;
	MSCP_LOG_MSG("%s\r\n",pathname);
	pfile = fopen(pathname, "r");
	if (NULL != pfile)
	{
		(void)fseek(pfile, (long int)0, SEEK_END);
		/*- 获取文件长度*/
		fileSize = (CM_UINT64)ftell(pfile);
		(void)fseek(pfile, 0, SEEK_SET);
	    /*- 读取文件*/
	    if(0u == fread(fileBuf, (size_t)fileSize, 1u, pfile))
	    {
			MSCP_LOG_MSG("PFM_MD5_Calc	fread error!!!\n");
	    }
	    else
	    {
			/*- 计算文件MD5*/
			(void)CM_MD5_Calc(fileBuf, (CM_UINT32)fileSize, Md5buf);
			rt = ENUM_CM_TRUE;
	    }		
	}
	else
	{
		MSCP_LOG_MSG("PFM_MD5_Calc  fopen %s error!!!\n",pathname);
	}
	return rt;
}

/**
* @brief 远程部署透传报文发送
* @param ResponseBuf 应答报文
* @param ResponseBufLen 应答报文长度
* @return 处理结果
* - ENUM_CM_TRUE 成功
* - ENUM_CM_FALSE 失败
*/
ENUM_CM_RETURN PFM_InnetRemoteUpdate_Send(IN CM_UINT8 ResponseBuf[],IN CM_UINT16 ResponseBufLen)
{
	ENUM_CM_RETURN rt = ENUM_CM_FALSE; /* 函数返回值 */
	STRU_PFM_INNET_CFG_T* pCom = NULL;/* 通信配置 */

	/*- 获取目的IP端口 */
	pCom = PFM_INI_InnetID2Addr(g_Maintenance_Id);
    /*- 是否获取成功 */
    if ((NULL != ResponseBuf) && (NULL != pCom))
    {
        /*- 本机是否为CPU1 */
        if (1u == g_RMUP_Cfg.CPU_ID)
        {
            /*- 从绿网通道发送 */
            (void)CFM_InnetRemoteUpdate_Send(ResponseBuf, (CM_INT32)CM_UNSIGNED_SHORT_EXP(ResponseBufLen), pCom->IP_G, pCom->Port_Raw_G);   /* parasoft-suppress MISRA2004-17_1 "指针运算提高代码执行效率" */
        }
        else
        {
            /*- 从紫网通道发送 */
            (void)CFM_InnetRemoteUpdate_Send(ResponseBuf, (CM_INT32)CM_UNSIGNED_SHORT_EXP(ResponseBufLen), pCom->IP_P, pCom->Port_Raw_P);   /* parasoft-suppress MISRA2004-17_1 "指针运算提高代码执行效率" */
        }
		rt = ENUM_CM_TRUE;
    }
    else
	{
		MSCP_LOG_MSG("PFM_InnetRemoteUpdate_Send  PFM_INI_InnetID2Addr error!\n");
	}
	
	return rt;	
}

/**
* @brief 文件更新请求命令处理
* @param RequestBuf[] 待处理数据帧
* @param RequestLen 待处理数据帧长度
* @return 处理结果
* - ENUM_CM_TRUE 成功
* - ENUM_CM_FALSE 失败
*/
ENUM_CM_RETURN PFM_FileUpdate_Request(IN CM_UINT8 RequestBuf[],IN CM_UINT16 RequestLen,OUT CM_UINT8 *Result)
{
	ENUM_CM_RETURN rt = ENUM_CM_FALSE; /* 函数返回值 */
	CM_UINT16 framelen = 0u;/* 帧长度 */
	CM_UINT8 frametype = 0u;  /* 帧类型 */
	CM_UINT8 updatetype = 0u;  /* 部署方式 */
	CM_UINT8 s_Filesum = 0u; /**< 文件数量 */
	STRU_FILE_UPDATE_CTRL_T s_FileUpdateMsg[FILE_MAX_QUANTITY];
	CM_UINT32 timeStamp = 0u;  /* 时间戳 */
	CM_UINT8 command = 0u;  /* 文件更新请求命令 */
	CM_UINT32 crc = 0u;   /* 文件更新请求报文CRC */
	CM_UINT32 crctmp = 0u;   /* 计算文件更新请求报文CRC */
	CM_UINT16 index = 0u;/* 数组下标 */
	CM_UINT16 loop_index = 0u;/* 循环数组下标 */
	CM_UINT8 Authorization_Status = 0u;  /* 授权状态 */
	CM_UINT8 Authorization_Reason = 0u;  /* 授权原因 */

	if (NULL != RequestBuf)
	{
	    /*- 解析设备退出运营命令再次请求帧 */
        /*
        2字节 帧长度
        1字节 帧类型
        4字节 时间戳
        1字节 部署方式
        1字节 文件更新请求命令
        1字节 文件数量
        2字节 文件名长度
        n字节 文件名
        16字节 文件md5值
        4字节 CRC
        */
		framelen = CM_ShortFromChar(&RequestBuf[index]);
		index += 2u;
		if (framelen != RequestLen - 2u)
		{
			MSCP_LOG_MSG("PFM_FileUpdate_Request framelen is error!!!\n");
			(void)CFM_DarkLog_Storage(DARK_LOG_HEX, TSCP_DARK_WARNING, 4U, DARK_FAULT_CODE_MERGE(REMOTE_UPDATE, DARK_FAULT_CODE_FUN_ORDER_1, TSCP_DARK_ASSERT_1));
		}
		else
		{
			
		}
		frametype = RequestBuf[index];
		index += 1u;
		timeStamp = CM_LongFromChar(&RequestBuf[index]);
		index += 4u;	
		updatetype = RequestBuf[index];
		index += 1u;
		command = RequestBuf[index];
		index += 1u;
		s_Filesum = RequestBuf[index];
		index += 1u;
		
		if (s_Filesum > FILE_MAX_QUANTITY)
		{
			MSCP_LOG_MSG("File Quantity more than FILE_MAX_QUANTITY!\n");
			(void)CFM_DarkLog_Storage(DARK_LOG_HEX, TSCP_DARK_WARNING, 4U, DARK_FAULT_CODE_MERGE(REMOTE_UPDATE, DARK_FAULT_CODE_FUN_ORDER_1, TSCP_DARK_ASSERT_2));
		}
		else
		{
			MSCP_LOG_MSG("Loop through parsing update file information\n");
			/*- 循环遍历解析更新文件信息 */
			for(loop_index = 0u; loop_index < s_Filesum ; loop_index++)
			{
				s_FileUpdateMsg[loop_index].FileNameLen = CM_ShortFromChar(&RequestBuf[index]);
				index += 2u;
				(void)CM_Memcpy(s_FileUpdateMsg[loop_index].FileName, FILE_NAME_MAX_LEN, &RequestBuf[index], s_FileUpdateMsg[loop_index].FileNameLen);
				index += s_FileUpdateMsg[loop_index].FileNameLen;

				(void)CM_Memcpy(s_FileUpdateMsg[loop_index].md5, CM_MD5_SIZE_BYTE, &RequestBuf[index], CM_MD5_SIZE_BYTE);
				index += CM_MD5_SIZE_BYTE;				
			}
		}
		
		crc = CM_LongFromChar(&RequestBuf[index]);
		index += 4u;
		
		if(framelen > 4u)
		{
			/*- 计算CRC */
			crctmp = CM_Crc32(&RequestBuf[2],framelen-4u);
		}
		else
		{
			MSCP_LOG_MSG("enter crc32 len is err = %d\n",framelen-4u);
		}

		
		/*- 判断sftp服务是否正常 */
		/*rt = PFM_SftpIsOk();*/
		rt = ENUM_CM_TRUE;/*默认开启-该功能预留*/
		/*- 文件更新请求命令CRC、命令、运行状态校验 */
		if ((ENUM_CM_TRUE !=rt ) || (crc != crctmp) || (0xaau != command))
		{
			MSCP_LOG_MSG("p crc = %d,m crc = %d\n, rt = %d, command = %d\n", crc, crctmp, rt, command);
            (void)CFM_DarkLog_Multiple(DARK_LOG_HEX, TSCP_DARK_PFMREMOTEUPDATE_FILEUPDATEREQUEST1, 4, \
            					sizeof(CM_UINT32),crc,
            					sizeof(CM_UINT32),crctmp,
            					sizeof(CM_UINT8),rt,
								sizeof(CM_UINT8),command);
			Authorization_Status = 0x01u;/* 禁止文件更新 */
			if(ENUM_CM_FALSE == rt)
			{
				Authorization_Reason = 0x02u;/* sftp未启动 */
				MSCP_LOG_MSG("Authorization_Reason = %x\n",Authorization_Reason);
			}
			else
			{
				Authorization_Reason = 0x01u;/* 合法性校验失败 */
				MSCP_LOG_MSG("Authorization_Reason = %x\n",Authorization_Reason);
			}
			(void)CFM_DarkLog_Storage(DARK_LOG_HEX, TSCP_DARK_PFMREMOTEUPDATE_FILEUPDATEREQUEST2, 1U, &Authorization_Reason);
			MSCP_LOG_MSG("PFM_FileUpdate_Reponse Validity Check Error!!!\n");
		}
		else
		{
			/*- 判断是否是可维护 */
			if ((ENUM_BOARDSTATE_EXIT == g_boardState) || (ENUM_BOARDSTATE_UPDATE == g_boardState))
			{
				/*- 非运行状态 */
				Authorization_Status = 0x00u;/* 允许文件更新 */
				Authorization_Reason = 0x00u;/* 默认值 */
				*Result = 0x01u; 
			}
			else
			{
				/*- 运行状态 */
				Authorization_Status =0x01u;/* 禁止文件更新 */
				Authorization_Reason = 0x03u;/* 原因：板卡状态异常 */
			}
		}
		/*- 文件更新请求命令确认处理 */
		rt = PFM_FileUpdate_Response(timeStamp,Authorization_Status,Authorization_Reason);
		if (ENUM_CM_TRUE == rt)
		{
			/*- 成功无处理 */
		}
		else
		{
			(void)CFM_DarkLog_Storage(DARK_LOG_HEX, TSCP_DARK_WARNING, 4U, DARK_FAULT_CODE_MERGE(REMOTE_UPDATE, DARK_FAULT_CODE_FUN_ORDER_2, TSCP_DARK_ASSERT_1));
			MSCP_LOG_MSG("PFM_FileUpdate_Reponse fail!!!\n");
		}
	}
	else
	{
		(void)CFM_DarkLog_Storage(DARK_LOG_HEX, TSCP_DARK_WARNING, 4U, DARK_FAULT_CODE_MERGE(REMOTE_UPDATE, DARK_FAULT_CODE_FUN_ORDER_2, TSCP_DARK_ASSERT_2));
		MSCP_LOG_MSG("RequestBuf is NULL!\n");
	}
	return rt;	
}

/**
* @brief 文件更新请求命令确认处理
* @param TimeStamp 请求报文时间戳
* @param State 授权状态
* @param Reason 授权原因
* @return 处理结果
* - ENUM_CM_TRUE 成功
* - ENUM_CM_FALSE 失败
*/
ENUM_CM_RETURN PFM_FileUpdate_Response(IN CM_UINT32 TimeStamp,IN CM_UINT8 State,IN CM_UINT8 Reason)
{
	ENUM_CM_RETURN rt = ENUM_CM_FALSE; /* 函数返回值 */
	CM_UINT32 crctmp = 0u;   /* 计算文件更新请求报文CRC */
	CM_UINT8 ResponseBuf[1024] = { 0u };  /* 确认报文缓冲区 */
	CM_UINT16 index = 0u;/* 数组下标 */
	/*STRU_PFM_INNET_CFG_T* pCom = NULL;*//* 通信配置 */

    /*- 打包文件更新请求确认帧 */
    /*
    2字节 帧长度
    1字节 帧类型
    4字节 时间戳
    1字节 授权状态
    1字节 授权原因
    4字节 CRC
    */
	CM_ShortToChar(11u, &ResponseBuf[index]);
    index += 2u;
	ResponseBuf[index] = 0x53u;
	index += 1u;
	CM_LongToChar(TimeStamp, &ResponseBuf[index]);
	index +=4u;	
	ResponseBuf[index] = State;
	index += 1u;
	ResponseBuf[index] = Reason;
	index += 1u;

	/*- 计算CRC */
	crctmp = CM_Crc32(&ResponseBuf[2],index-2u);
	CM_LongToChar(crctmp, &ResponseBuf[index]);
	index +=4u;

	/*- 文件更新请求确认帧发送 */
	rt = PFM_InnetRemoteUpdate_Send(ResponseBuf,index);
	if (ENUM_CM_TRUE != rt)
	{
		(void)CFM_DarkLog_Storage(DARK_LOG_HEX, TSCP_DARK_WARNING, 4U, DARK_FAULT_CODE_MERGE(REMOTE_UPDATE, DARK_FAULT_CODE_FUN_ORDER_3, TSCP_DARK_ASSERT_1));
		MSCP_LOG_MSG("PFM_FileUpdate_Response Call PFM_InnetRemoteUpdate_Send Error!!\n");
	}
	else
	{
		/*- 成功无处理 */
	}
	return rt;	
}

/**
* @brief 文件上传完成验证请求命令处理
* @param RequestBuf[] 待处理数据帧
* @param RequestLen 待处理数据帧长度
* @return 处理结果
* - ENUM_CM_TRUE 成功
* - ENUM_CM_FALSE 失败
*/
ENUM_CM_RETURN PFM_FileVerity_Request(IN CM_UINT8 RequestBuf[],IN CM_UINT16 RequestLen)
{
	ENUM_CM_RETURN rt = ENUM_CM_FALSE; /* 函数返回值 */
	CM_UINT16 framelen = 0u;/* 帧长度 */
	CM_UINT8 frametype = 0u;  /* 帧类型 */
	CM_UINT8 updatetype = 0u;  /* 部署方式 */
	CM_UINT8 s_Filesum = 0u; /**< 文件数量 */
	STRU_FILE_UPDATE_CTRL_T s_FileUpdateMsg[FILE_MAX_QUANTITY];
	CM_UINT32 timeStamp = 0u;  /* 时间戳 */
	CM_UINT8 command = 0u;  /* 文件更新请求命令 */
	CM_UINT32 crc = 0u;   /* 文件更新请求报文CRC */
	CM_UINT32 crctmp = 0u;   /* 计算文件更新请求报文CRC */
	CM_UINT16 index = 0u;/* 数组下标 */
	CM_UINT8 loop_index = 0u;/* 循环数组下标 */
	CM_UINT16 filemsg_index = 0u;/* 循环数组下标 */
	CM_UINT16 FileNameLen;		  /**< 文件名长度 */
	CM_UINT8 FileName[FILE_NAME_MAX_LEN];	/**< 文件名 */

	if (NULL != RequestBuf)
	{
	    /*- 解析文件上传完成验证请求帧 */
        /*
        2字节 帧长度
        1字节 帧类型
        4字节 时间戳
        1字节 部署方式
        1字节 上传完成验证请求命令
        1字节 文件数量
        2字节 文件名长度
        n字节 文件名
        16字节 文件md5值
        4字节 CRC
        */
		framelen = CM_ShortFromChar(&RequestBuf[index]);
		index += 2u;
		frametype = RequestBuf[index];
		index += 1u;
		timeStamp = CM_LongFromChar(&RequestBuf[index]);
		index += 4u;	
		updatetype = RequestBuf[index];
		index += 1u;
		command = RequestBuf[index];
		index += 1u;
		s_Filesum = RequestBuf[index];
		index += 1u;
		
		if (s_Filesum > FILE_MAX_QUANTITY)
		{
			MSCP_LOG_MSG("File Quantity more than FILE_MAX_QUANTITY!\n");
		}
		else
		{
			/*- 循环遍历解析更新文件信息 */
			for(filemsg_index = 0u; filemsg_index < s_Filesum ; filemsg_index++)
			{
				FileNameLen = CM_ShortFromChar(&RequestBuf[index]);
				index += 2u;
				(void)CM_Memcpy(FileName, FILE_NAME_MAX_LEN, &RequestBuf[index], FileNameLen);
				index += FileNameLen;

				rt = PFM_FindFileByPath(FileName,FileNameLen);
				if (ENUM_CM_TRUE != rt)
				{
					(void)CFM_DarkLog_Storage(DARK_LOG_HEX, TSCP_DARK_WARNING, 4U, DARK_FAULT_CODE_MERGE(REMOTE_UPDATE, DARK_FAULT_CODE_FUN_ORDER_4, TSCP_DARK_ASSERT_1));
					MSCP_LOG_MSG("Find File %s error!\n",FileName);
				}
				else
				{
					s_FileUpdateMsg[loop_index].FileNameLen = FileNameLen;
					(void)CM_Memcpy(s_FileUpdateMsg[loop_index].FileName, FILE_NAME_MAX_LEN, FileName, FileNameLen);
					(void)CM_Memcpy(s_FileUpdateMsg[loop_index].md5, CM_MD5_SIZE_BYTE, &RequestBuf[index], CM_MD5_SIZE_BYTE);
					loop_index++;
				}
				index += CM_MD5_SIZE_BYTE;			
			}
		}
		
		crc = CM_LongFromChar(&RequestBuf[index]);
		index += 4u;
		
		if(framelen > 4u)
		{
			/*- 计算CRC */
			crctmp = CM_Crc32(&RequestBuf[2],framelen-4u);
			MSCP_LOG_MSG("crc = %u,crctmp=%u\n",crc,crctmp);
		}
		else
		{
			MSCP_LOG_MSG("crc32 len is err = %d\n", framelen-4u);
		}

		
		/*- 文件上传完成验证请求命令CRC、命令、运行状态、文件查找校验 */
		if ((crc != crctmp) || (0xaau != command))
		{
			/* 合法性校验失败，丢弃处理 */
			(void)CFM_DarkLog_Storage(DARK_LOG_HEX, TSCP_DARK_WARNING, 4U, DARK_FAULT_CODE_MERGE(REMOTE_UPDATE, DARK_FAULT_CODE_FUN_ORDER_4, TSCP_DARK_ASSERT_2));
			MSCP_LOG_MSG("PFM_FileVerity_Request Validity check failure!!!\n");
			rt =ENUM_CM_FALSE;
		}
		else
		{
			/*- 文件上传完成验证命令确认处理 */
			rt = PFM_FileVerity_Response(timeStamp,s_FileUpdateMsg,loop_index);
			if ((ENUM_CM_TRUE == rt) && (0u < Filesum_check_cur))
			{
				/*- 成功无处理 */
			}
			else
			{
				rt = ENUM_CM_FALSE;
				(void)CFM_DarkLog_Storage(DARK_LOG_HEX, TSCP_DARK_WARNING, 4U, DARK_FAULT_CODE_MERGE(REMOTE_UPDATE, DARK_FAULT_CODE_FUN_ORDER_4, TSCP_DARK_ASSERT_3));
				MSCP_LOG_MSG("PFM_FileVerity_Response fail!!!\n");
			}
		}
	}
	else
	{
		(void)CFM_DarkLog_Storage(DARK_LOG_HEX, TSCP_DARK_WARNING, 4U, DARK_FAULT_CODE_MERGE(REMOTE_UPDATE, DARK_FAULT_CODE_FUN_ORDER_4, TSCP_DARK_ASSERT_4));
		MSCP_LOG_MSG("RequestBuf is NULL!\n");
	}
	return rt;	
}

/**
* @brief 文件上传完成验证命令确认处理
* @param FileUpdateMsg[] 文件验证信息数组
* @param Quantity 文件验证信息数组元素数量
* @return 处理结果
* - ENUM_CM_TRUE 成功
* - ENUM_CM_FALSE 失败
*/
ENUM_CM_RETURN PFM_FileVerity_Response(IN CM_UINT32 TimeStamp,IN STRU_FILE_UPDATE_CTRL_T FileUpdateMsg[],IN CM_UINT8 Quantity)
{
	/*- 变量初始化 */
	ENUM_CM_RETURN rt = ENUM_CM_FALSE; /* 函数返回值 */
	CM_UINT32 crctmp = 0u;   /* 计算文件更新请求报文CRC */
	CM_UINT8 ResponseBuf[1024] = { 0u };  /* 确认报文缓冲区 */
	CM_UINT16 index = 0u;/* 发送数组下标 */
	CM_UINT8 loop_index = 0u;/* 循环数组下标 */
	CM_UINT8 md5buftmp[CM_MD5_SIZE_BYTE] = { 0u };  /* md5临时缓冲区 */
	CM_INT32 ret = 0; /* 返回值 */
	CM_UINT8 pathnametmp[FILE_NAME_MAX_LEN]={0u};
	CM_UINT8 i = 0u;
	CM_UINT8 Filesum_index = 0u;/* 遍历结构体数组*/
	CM_UINT8 Filesum_flag = 0u;/*找到标志，找到相同文件名为1，没找到清0*/

    /*- 文件上传验证确认帧 */
    /*
    2字节 帧长度
    1字节 帧类型
    4字节 时间戳
    1字节 已验证文件数量
	2字节 文件名长度
	n字节 文件名
	16字节 文件md5值
    4字节 CRC
    */
    Filesum_check_cur = 0u; /**< 已验证文件数量 */
	
    index += 2u;
	ResponseBuf[index] = 0x54u;
	index += 1u;
	CM_LongToChar(TimeStamp, &ResponseBuf[index]);
	index +=4u;	

	index +=1u;
	
	/*- 计算md5 */
	for(loop_index = 0u;loop_index <Quantity; loop_index++)
	{
		(void)CM_Memset(pathnametmp,0u,FILE_NAME_MAX_LEN,sizeof(pathnametmp));
		(void)strcat(pathnametmp,g_RMUP_Cfg.Start_Path);
		(void)strcat(pathnametmp,"/Backup/");
		(void)strcat(pathnametmp,FileUpdateMsg[loop_index].FileName);
		(void)PFM_MD5_Calc(pathnametmp,FileUpdateMsg[loop_index].FileNameLen,md5buftmp);
		/*- 比较读取文件的md5和存储的md5是否相同*/
		ret = CM_Memcmp(md5buftmp,FileUpdateMsg[loop_index].md5,CM_MD5_SIZE_BYTE);
		if (0!=ret)
		{
			MSCP_LOG_MSG("file name %s md5 check error!!\r\n",FileUpdateMsg[loop_index].FileName);
			for(i = 0u; i < CM_MD5_SIZE_BYTE; i++)
			{
				MSCP_LOG_MSG("0x%x ",md5buftmp[i]);
			}
			for(i = 0u; i < CM_MD5_SIZE_BYTE; i++)
			{
				MSCP_LOG_MSG("0x%x ",FileUpdateMsg[loop_index].md5[i]);
			}
			/*- 删除错误文件 */
			PFM_RM_File(FileUpdateMsg[loop_index].FileName);
		}
		else
		{
            CM_ShortToChar(FileUpdateMsg[loop_index].FileNameLen, &ResponseBuf[index]);
            index +=2u;
            (void)CM_Memcpy(&ResponseBuf[index], sizeof(ResponseBuf)-index, &FileUpdateMsg[loop_index].FileName, FileUpdateMsg[loop_index].FileNameLen);
            index +=FileUpdateMsg[loop_index].FileNameLen;
            (void)CM_Memcpy(&ResponseBuf[index], sizeof(ResponseBuf)-index, &FileUpdateMsg[loop_index].md5, CM_MD5_SIZE_BYTE);
            index +=CM_MD5_SIZE_BYTE;
            Filesum_check_cur++;
            for(Filesum_index = 0u;Filesum_index  < Filesum_check;Filesum_index++)
            {
            	if(FileUpdateMsg[loop_index].FileNameLen == s_FileUpdateSucess[Filesum_index].FileNameLen)
            	{
            		if(0 == CM_Memcmp(s_FileUpdateSucess[Filesum_index].FileName,FileUpdateMsg[loop_index].FileName,FileUpdateMsg[loop_index].FileNameLen))
            		{
            			Filesum_flag = 1u;
            			break;
            		}
            		else
            		{
            			Filesum_flag = 0u;
            		}
            	}
            	else
            	{
            		Filesum_flag = 0u;
            	}
            }
            /*- 无论是否找到相同文件名，下标都是Filesum_index*/
        	s_FileUpdateSucess[Filesum_index].FileNameLen = FileUpdateMsg[loop_index].FileNameLen;
			(void)CM_Memcpy(&s_FileUpdateSucess[Filesum_index].FileName, sizeof(s_FileUpdateSucess[Filesum_index].FileName), &FileUpdateMsg[loop_index].FileName, FileUpdateMsg[loop_index].FileNameLen);
			(void)CM_Memcpy(&s_FileUpdateSucess[Filesum_index].md5, sizeof(s_FileUpdateSucess[Filesum_index].md5), &FileUpdateMsg[loop_index].md5, CM_MD5_SIZE_BYTE);
			/*- 未找到相同文件名，新增文件信息*/
            if(0u == Filesum_flag)
            {
            	Filesum_check++;
            }
		}
	}
	/*- 已验证文件数量 */
	ResponseBuf[7] = Filesum_check_cur;
	/*- 计算CRC */
	crctmp = CM_Crc32(&ResponseBuf[2],index-2u);
	CM_LongToChar(crctmp, &ResponseBuf[index]);
	index +=4u;
	/*- 帧长度 */
	CM_ShortToChar(index - 2u, ResponseBuf);

	/*- 文件上传完成验证确认帧发送 */
	rt = PFM_InnetRemoteUpdate_Send(ResponseBuf,index);
	if (ENUM_CM_TRUE != rt)
	{
		(void)CFM_DarkLog_Storage(DARK_LOG_HEX, TSCP_DARK_WARNING, 4U, DARK_FAULT_CODE_MERGE(REMOTE_UPDATE, DARK_FAULT_CODE_FUN_ORDER_5, TSCP_DARK_ASSERT_1));
		MSCP_LOG_MSG("PFM_FileVerity_Response Call PFM_InnetRemoteUpdate_Send Error!!\n");
	}
	else
	{
		/*- 成功无处理 */
	}
	
	return rt;	
}

/**
* @brief 重启过程校验
* @return 授权状态
* @param 无
*/
CM_UINT8 PFM_RmUp_Check(void)
{
	/*- 变量初始化  */
	CM_UINT8 rt = 0u; /* 函数返回值为成功 */
	/*- 如果crc计算错误  */
	if((1 == reasonAuthorization) && (1 == packAccredit))
	{
		/*- 授权原因置为crc计算错误  */
		rt = 1u;
		reasonAuthorization = 1u;
		(void)CFM_DarkLog_Storage(DARK_LOG_HEX, TSCP_DARK_WARNING, 4U, DARK_FAULT_CODE_MERGE(REMOTE_UPDATE, DARK_FAULT_CODE_FUN_ORDER_6, TSCP_DARK_ASSERT_1));
		MSCP_LOG_MSG("**************** remote crc error  ****************\n");
	}
	/*- 如果是升级重启,并且更新过文件  */
	else if ((0xaau == reboottype) && (0x02u == g_RemoteUpdate_State))
	{
		/*- 授权原因默认为升级重启  */
		MSCP_LOG_MSG("**************** remote update reboot ****************\n");
	}
	/*- 如果是升级重启,但是未更新过文件  */
	else if(0xaau == reboottype)
	{
		/*- 授权原因置为未获取到待更新状态,重启失败  */
		(void)CFM_DarkLog_Storage(DARK_LOG_HEX, TSCP_DARK_WARNING, 4U, DARK_FAULT_CODE_MERGE(REMOTE_UPDATE, DARK_FAULT_CODE_FUN_ORDER_6, TSCP_DARK_ASSERT_2));
		MSCP_LOG_MSG("reboottype = %x,never receive frame 0xa4\n",reboottype);
		rt = 1u;
		reasonAuthorization = 2u;
	}
	else
	{
		/*- 维护重启  */
		MSCP_LOG_MSG("**************** breakdown or maintenance reboot ****************\n");
	}

	/*- 是否重启成功  */
	return rt;
}

/**
* @brief 执行远程重启
* @param 无
*/
void PFM_RemoteUpdate_Reboot(void)
{
	CM_UINT8 cmd[128]={0u};
	CM_UINT16 loop_index = 0u;/* 循环数组下标 */
	CM_UINT8 pathnametmp[FILE_NAME_MAX_LEN]={0u};
	CM_UINT8 md5buftmp[CM_MD5_SIZE_BYTE] = { 0u };  /* md5临时缓冲区 */
	CM_INT32 ret = 0; /* 返回值 */
	CM_UINT8 compareflag = 0u; /* 比较标志,0成功1失败 */
	FILE * fp_updatesucess;
	FILE * fp_rebootlog;
	CM_CHAR str_reboot[256] = {0};
	ENUM_BOARD_STATE_T boardState = PFM_GetBoardState();

	if(0u == packAccredit)
	{
		/* 远程升级重启文件夹拷贝和文件校验 */
		if ((0xaau == reboottype) && (0x02u == g_RemoteUpdate_State))
		{
			MSCP_LOG_MSG("**************** remote update reboot ****************\n");
			for(loop_index = 0u;loop_index<Filesum_check;loop_index++)
			{
				(void)CM_Memset(cmd,0u,128,sizeof(cmd));
				(void)strcat(cmd,"cp ");
				(void)strcat(cmd,g_RMUP_Cfg.Start_Path);
				(void)strcat(cmd,"/Backup/");
				(void)strcat(cmd,s_FileUpdateSucess[loop_index].FileName);
				(void)strcat(cmd," ");
				(void)strcat(cmd,g_RMUP_Cfg.Start_Path);
				(void)strcat(cmd,"/Storage/");
				(void)system(cmd);
				CM_Sleep(100u);
			}
			
			CM_Sleep(5u);
			
			for(loop_index = 0u;loop_index<Filesum_check;loop_index++)
			{
				(void)CM_Memset(pathnametmp,0u,FILE_NAME_MAX_LEN,sizeof(pathnametmp));
				(void)strcat(pathnametmp,g_RMUP_Cfg.Start_Path);
				(void)strcat(pathnametmp,"/Storage/");
				(void)strcat(pathnametmp,s_FileUpdateSucess[loop_index].FileName);
				(void)PFM_MD5_Calc(pathnametmp,s_FileUpdateSucess[loop_index].FileNameLen,md5buftmp);
				/*- 比较读取文件的md5和存储的md5是否相同*/
				ret = CM_Memcmp(md5buftmp,s_FileUpdateSucess[loop_index].md5,CM_MD5_SIZE_BYTE);
				if (0 != ret)
				{
					compareflag = 1u;
					(void)CFM_DarkLog_Storage(DARK_LOG_HEX, TSCP_DARK_WARNING, 4U, DARK_FAULT_CODE_MERGE(REMOTE_UPDATE, DARK_FAULT_CODE_FUN_ORDER_7, TSCP_DARK_ASSERT_1));
					MSCP_LOG_MSG("Move %s From Backup To Storage And Copmare Md5 Failed!!!\n",s_FileUpdateSucess[loop_index].FileName);
					/*- 跳出 */
					break;
				}
				else
				{
					MSCP_LOG_MSG("Move %s From Backup To Storage And Copmare Md5 Sucess!!!\n",s_FileUpdateSucess[loop_index].FileName);
				}
			}
			if ((0u == compareflag) && (0u < Filesum_check))
			{	
				fp_updatesucess = fopen("RmUpSucess.txt", "w+");
				MSCP_LOG_MSG("**************** RmUpSucess.txt ****************\n");
				(void)fclose(fp_updatesucess);
				MSCP_LOG_MSG("**************** remote update reboot ****************\n");
			}
			else
			{

			}
		}
		else
		{
			MSCP_LOG_MSG("**************** breakdown or maintenance reboot ****************\n");
			if(ENUM_BOARDSTATE_DEFAULT == boardState)
			{
				/*- 故障软重启，需要保存次数文件*/
				fp_rebootlog = fopen("rebootlog.txt", "w+");
				/*- 允许重启，根据重启条件判断写入文件次数*/
				(void)sprintf(str_reboot,"0x%x\n",s_FaultRebootCut + 1);
				ret = fwrite(str_reboot,(CM_SIZE_T)1u,strlen(str_reboot),fp_rebootlog);
				if (ret != strlen(str_reboot))
				{
					MSCP_LOG_MSG("fwrite rebootlog.txt fail!\n");
					(void)printf("fwrite rebootlog.txt fail!\n");
				}
				else
				{
					/*- 无处理 */
				}
				(void)fclose(fp_rebootlog);
			}
			else
			{
				MSCP_LOG_MSG("boardState = %d\n",boardState);
			}
		}
		
		MSCP_LOG_MSG("**************** going to restart the system ****************\n");

		(void)CM_Memset(cmd,0u,128,sizeof(cmd));
		(void)strcat(cmd,"rm -rf ");
		(void)strcat(cmd,g_RMUP_Cfg.Start_Path);
		(void)strcat(cmd,"/Backup/*");
		(void)system(cmd);

		/*- 延时1秒重启 */
		CM_Sleep(1000u);
		(void)system("shutdown");
		/*- 休眠等待重启 */
		CM_Sleep(CM_UINT32_MAX);
	}
	else
	{
		/**重置状态*/
		packAccredit = 2u; /**当变量置为0或者1,则需要处理远程重启请求报文*/
		reasonAuthorization = 0u; /*授权原因*/
		s_countres = 0u;
	}

}
/**
* @brief 获取重启状态
* @return 板卡重启状态  取值范围：0x55:未更新重启、0xaa:升级重启 0xd1~d7:硬重启
*/
CM_UINT8 PFM_GetBoardRebootState(void)
{
	/*- 获取重启状态 */
	return reboottype;
}
/**
* @brief 获取板卡运行状态
* @return 板卡运行状态
* - ENUM_BOARDSTATE_ERROR = 0,   未知状态
* - ENUM_BOARDSTATE_RUN = 1,     运行状态
* - ENUM_BOARDSTATE_EXIT = 2,    退出运营状态
* - ENUM_BOARDSTATE_UPDATE = 3,  故障可更新文件状态
* - ENUM_BOARDSTATE_DEFAULT = 4, 故障不可更新文件状态
*/
ENUM_BOARD_STATE_T PFM_GetBoardState(void)
{
	return g_boardState;
}

/**
* @brief 设置板卡运行状态
* @param state 板卡运行状态
* - ENUM_BOARDSTATE_ERROR = 0,   未知状态
* - ENUM_BOARDSTATE_RUN = 1,     运行状态
* - ENUM_BOARDSTATE_EXIT = 2,    退出运营状态
* - ENUM_BOARDSTATE_UPDATE = 3,  故障可更新文件状态
* - ENUM_BOARDSTATE_DEFAULT = 4, 故障不可更新文件状态
*/
void PFM_SetBoardState(ENUM_BOARD_STATE_T state)
{
	g_AppSetboardState = state;
	g_boardState = state;
}
/**
* @brief 应用设置板卡临时运行状态
* @param state 板卡运行状态 取值范围：
* - ENUM_BOARDSTATE_ERROR = 0,   未知状态
* - ENUM_BOARDSTATE_RUN = 1,     运行状态
* - ENUM_BOARDSTATE_EXIT = 2,    退出运营状态
* - ENUM_BOARDSTATE_UPDATE = 3,  故障可更新文件状态
* - ENUM_BOARDSTATE_DEFAULT = 4, 故障不可更新文件状态
*/
void PFM_SetBoardState_APP(ENUM_BOARD_STATE_T state)
{
	/*- 应用设置板卡临时运行状态 */
	g_AppSetboardState = state;
}
/**
* @brief 周期将设备状态信息发送给部署工具客户端
* @return 函数执行结果
* - 0x55u成功
* - 0xAAu失败
* @note
* 周期将设备状态信息发送给部署工具客户端
* 组数据->写进协议
* 注：此函数调用必须在周期主线程封装输出数据之前
*/
ENUM_CM_RETURN PFM_DevStateSend(CM_UINT8 ifCyc)
{
	/*- 变量初始化 */
	ENUM_CM_RETURN ret = ENUM_CM_FALSE;
	CM_INT32 rxLen = 0;
	CM_UINT8 txBuf[1000] = {0u};
	CM_UINT8 rxBuf[1000] = {0u};
	CM_UINT16 dstName = 0u;
	CM_UINT16 txLen = 0u;
	CM_UINT8 m2x2State = 0u;
	static CM_UINT32 DevStateSendIndex = 0u;
	CM_UINT8 DrvBoardCpu_ID = 0U;         /**< 板卡cpuID */
	CM_UINT32 crc;
	CM_UINT16 offset = 0u;
	CM_UINT16 fileNameLen = 20u;
	CM_UINT16 fileMd5Len = 16u;
	CM_UINT8 i = 0;

	MSCP_LOG_MSG("Maintenance Mode DevStateSendIndex = %d\n",DevStateSendIndex);
	if((0x00u != g_Maintenance_Id) && (0x55u == g_RMUP_Cfg.M_RemoteUpdate_Enable) && (0x55u == g_RMUP_Cfg.M_2oo2_Enable))
	{
		/* 总长度(临时添加) */
		txLen = 0u;
		CM_ShortToChar(txLen, &txBuf[offset]);
		offset += 2u;
		/* 帧类型 */
		txBuf[offset] = 0x50u;
		offset += 1u;
		/* 帧序号 */
		CM_LongToChar(DevStateSendIndex,&txBuf[offset]);
		offset += 4u;
		DevStateSendIndex++;
		/* 设备类型、id */
		CM_ShortToChar(g_RMUP_Cfg.OUTNET_ID, &txBuf[offset]);
		offset += 2u;
		/* 本系热备状态 */
		m2x2State = SFM_2x2_GetLocal2x2State();
		txBuf[offset] = m2x2State;
		offset += 1u;
		/* 板卡类型(主机板\通控板\串口板) */
		txBuf[offset] = 1u;
		offset += 1u;
		/* cpuid */
    	if(1u == g_RMUP_Cfg.BOARD_ID)
    	{
    		if(1u == g_RMUP_Cfg.CPU_ID)
    		{
    			DrvBoardCpu_ID = 0xA1u;
    		}
    		else
    		{
    			DrvBoardCpu_ID = 0xA2u;
    		}
    	}
    	else
    	{
    		if(1u == g_RMUP_Cfg.CPU_ID)
    		{
    			DrvBoardCpu_ID = 0xB1u;
    		}
    		else
    		{
    			DrvBoardCpu_ID = 0xB2u;
    		}
    	}
		txBuf[offset] = DrvBoardCpu_ID;
		offset += 1u;
		/* 板卡状态 */
		txBuf[offset] = g_boardState;
		offset += 1u;
		/* 主机板版本数量 */
		txBuf[offset] = 3u + g_App_Verson.versonNumber;
		offset += 1u;
		/* 平台版本 */
		txBuf[offset] = 1u;
		offset += 1u;
		txBuf[offset] = MSCP_SW_VERION[0];
		offset += 1u;
		txBuf[offset] = MSCP_SW_VERION[1];
		offset += 1u;
		txBuf[offset] = MSCP_SW_VERION[2];
		offset += 1u;
		txBuf[offset] = MSCP_SW_VERION[3];
		offset += 1u;
		/* qnx版本 */
		txBuf[offset] = 2u;
		offset += 1u;
		txBuf[offset] = TSCP_QNX_VERION[0];
		offset += 1u;
		txBuf[offset] = TSCP_QNX_VERION[1];
		offset += 1u;
		txBuf[offset] = TSCP_QNX_VERION[2];
		offset += 1u;
		txBuf[offset] = TSCP_QNX_VERION[3];
		offset += 1u;
		/* 应用版本 数据版本 scard版本*/
		for(i = 0; i < 3; i++)
		{
			if(1 == g_App_Verson.registerVerson[i].flag)
			{
				txBuf[offset] = g_App_Verson.registerVerson[i].versonName + 2;
				offset += 1u;
				txBuf[offset] = g_App_Verson.registerVerson[i].verson[0];
				offset += 1u;
				txBuf[offset] = g_App_Verson.registerVerson[i].verson[1];
				offset += 1u;
				txBuf[offset] = g_App_Verson.registerVerson[i].verson[2];
				offset += 1u;
				txBuf[offset] = g_App_Verson.registerVerson[i].verson[3];
				offset += 1u;
			}
		}
		/* 驱动版本 */
		txBuf[offset] = 6u;
		offset += 1u;
		txBuf[offset] = MSCP_DRV_VERION[0];
		offset += 1u;
		txBuf[offset] = MSCP_DRV_VERION[1];
		offset += 1u;
		txBuf[offset] = MSCP_DRV_VERION[2];
		offset += 1u;
		txBuf[offset] = MSCP_DRV_VERION[3];
		offset += 1u;
		/* 主机板文件数量  app、main_base、fs */
		txBuf[offset] = 1u;
		offset += 1u;
		/* app文件 */
		CM_ShortToChar(fileNameLen, &txBuf[offset]);
		offset += 2u;
		(void)CM_Memcpy(&txBuf[offset],fileNameLen,g_RMUP_Cfg.APP_NAME,fileNameLen);
		offset += fileNameLen;
		(void)CM_Memcpy(&txBuf[offset],fileMd5Len,g_RMUP_Cfg.APP_MD5,fileMd5Len);
		offset += fileMd5Len;
		/* CRC(小crc从热备状态开始计算) */
		crc = CM_Crc32(&txBuf[9], offset-9u);
		CM_LongToChar(crc, txBuf + offset);  /*CRC*/
		offset += 4u;
		/*- 2oo2交换输出校验帧 */
		if(1 == ifCyc)
		{
			rxLen = SFM_2oo2_Exchange_Currency(txBuf, offset, rxBuf, 1000u, ENUM_2oo2_OUTPUT_EX);
		}
		else
		{
			rxLen = SFM_2oo2_Exchange_FullDuplex_Crash(txBuf, offset, rxBuf, 1000u, ENUM_2oo2_OUTPUT_EX);
		}
		/*- 检查2oo2双机的输出校验帧是否一致 */
		CM_ASSERT_MAINTAIN(offset == rxLen);
		/*- 设置设备id */
		dstName = g_Maintenance_Id;
		if(1u == g_RMUP_Cfg.CPU_ID)
		{
			(void)CM_Memcpy(txBuf+offset,1000u-offset,rxBuf+3u,rxLen-3u);
			/* 减去对方cpu的帧长度以及帧类型 */
			offset = offset*2u-3u;
			/*- 计算整包数据crc(不包含长度) */
			crc = CM_Crc32(&txBuf[2], offset - 2u);
			CM_LongToChar(crc, txBuf + offset);  /*CRC*/
			offset += 4u;
			/* 填入长度,总长是offset-自身2字节 */
			txLen = offset - 2u;
			CM_ShortToChar(txLen, &txBuf[0]);
	        ret = Prtcl_InnetSafe_RmSend(dstName, txBuf, offset);
			MSCP_LOG_MSG("offset = %d send ret =%d\n",offset, ret);
		}
		else
		{
			(void)CM_Memcpy(rxBuf+rxLen,1000u-rxLen,txBuf+3u,offset-3u);
			offset = offset*2u-3u;
			/*- 计算整包数据crc(不包含长度) */
			crc = CM_Crc32(&rxBuf[2], offset - 2u);
			CM_LongToChar(crc, rxBuf + offset);  /*CRC*/
			offset += 4u;
			/* 填入长度,总长是offset-自身2字节 */
			rxLen = offset - 2u;
			CM_ShortToChar(rxLen, &rxBuf[0]);
	        ret = Prtcl_InnetSafe_RmSend(dstName, rxBuf, offset);
			MSCP_LOG_MSG("offset = %d send ret = %d\n",offset, ret);
		}
	}
	else
	{
		/*- 无需处理*/
		MSCP_LOG_MSG("Unregistered application\n");
	}

	return ret;
}

/**
* @brief 远程重启命令接收处理
* @return 帧类型
* - 0xa5首次重启请求
* - 0xa6二次重启请求
* - 0x00非法包
*/
static CM_UINT8 PFM_DataReastart_Recv(void)
{
	/*- 变量初始化 */
	CM_UINT8 mData[1000] = { 0u };
	CM_UINT8 pData[1000] = { 0u };
	CM_UINT32 dataLen = 0u;
	CM_UINT16 pSrcLogicID = 0u;
	CM_UINT8 pLifeTime = 0u;
	CM_UINT32 dataOffset = 0u;
	CM_UINT16 packLen = 0u;
	CM_UINT8 packType = 0u;
	CM_UINT32 packCrc = 0u;
	CM_UINT32 calcCrc1 = 0u;
	CM_UINT32 calcCrc2 = 0u;
	CM_UINT8 packRestartMode = 0u; /*重启方式*/
	CM_UINT8 boardType = 0u;
	CM_UINT8 boardId = 0u;
	CM_UINT32 packRestartCrc = 0u; /*重启请求命令crc*/
    do
    {
        /*- 从内网安全协议读取应用接收报文 */
        dataLen = Prtcl_InnetSafe_PlatRmRecv(&pSrcLogicID, &pLifeTime, &mData[0], sizeof(mData));
        /*- 如果收到了数据 */
		if (0u < dataLen)
		{
			/*- 解包 */
			MSCP_LOG_MSG("PFM_DataProc_Crash dataLen = %d\n",dataLen);
			MSCP_LOG_MSG("\n");
			for(int i = 0; i < dataLen; i++)
			{
				MSCP_LOG_MSG("0x%0.2x ",mData[i]);
			}
			MSCP_LOG_MSG("\n");
	    	packLen = CM_ShortFromChar(&mData[dataOffset]);
	    	dataOffset += 2u;
	    	packType = mData[dataOffset];
			dataOffset +=1u;
			/*- 如果帧类型是一次请求确认 */
	    	if(0xa5 == packType)
	    	{
	    		/*- 按照一次请求确认帧继续解包 */
	    		boardType = mData[dataOffset];
	    		dataOffset +=1u;
	    		MSCP_LOG_MSG("boardType = %d\n",boardType);
	    		boardId = mData[dataOffset];
	    		dataOffset +=1u;
	    		MSCP_LOG_MSG("boardId = %d\n",boardId);
				s_packTimer = CM_LongFromChar(&mData[dataOffset]);
	    		dataOffset+=4u;
	    		MSCP_LOG_MSG("s_packTimer = %d\n",s_packTimer);
	    		packRestartMode = mData[dataOffset];
				dataOffset+=1u;
				MSCP_LOG_MSG("packRestartMode = %d\n",packRestartMode);
				reboottype = mData[dataOffset];
				dataOffset+=1u;
				MSCP_LOG_MSG("reboottype = %d\n",reboottype);
				packRestartCrc = CM_LongFromChar(&mData[dataOffset]);
				calcCrc1 = CM_Crc32(&mData[3], 8u);
				dataOffset+=4u;
	    		packCrc = CM_LongFromChar(&mData[dataOffset]);
				calcCrc2 = CM_Crc32(&mData[2], 13u);
				dataOffset+=4u;
				/*- crc以及重启方式是否正确 */
				if((packRestartCrc != calcCrc1) || (packCrc != calcCrc2))
				{
	    			packAccredit = 1u;
	    			reasonAuthorization = 1u;
	    			MSCP_LOG_MSG("0xa5 illegality packRestartCrc=%d,calcCrc1=%d,packCrc=%d,calcCrc2=%d,reboottype=%d\n",packRestartCrc,calcCrc1,packCrc,calcCrc2,reboottype);

				}
				else if((0x55u != reboottype) && (0xaau != reboottype))
				{
					packAccredit = 1u;
					reasonAuthorization = 6u;
					MSCP_LOG_MSG("0xa5 illegality:6 reboottype=%d\n",reboottype);
				}
				else if((FAULT_REBOOT_CUT_MAX <= s_FaultRebootCut) && (0x55u == reboottype))
				{
					/*- 远程-不更新重启-3次禁止故障重启*/
					packAccredit = 1u;
					reasonAuthorization = 4u;
					MSCP_LOG_MSG("0xa5 illegality:4 s_FaultRebootCut=%d\n",s_FaultRebootCut);
				}
				else
				{
					/*- 2oo2功能是否开启 */
					if (0x55u == g_RMUP_Cfg.M_2oo2_Enable)
					{
						/*- 2oo2 quit */
						(void)SFM_2oo2_Exchange_FullDuplex_Crash(&mData[0], 0, &pData[0], 0u, ENUM_2oo2_SHUTDOWNQUIT);
					}
					else
					{
						/*- 无处理 */
					}
					packAccredit = 0u;
					reasonAuthorization = 0u;
					MSCP_LOG_MSG("0xa5 reboottype = %d\n",reboottype);
				}
	    	}
	    	/*- 如果帧类型是二次请求确认 */
	    	else if(0xa6 == packType)
	    	{
	    		/*- 按照二次请求确认帧继续解包 */
	    		boardType = mData[dataOffset];
				dataOffset +=1u;
				MSCP_LOG_MSG("boardType = %d\n",boardType);
				boardId = mData[dataOffset];
				dataOffset +=1u;
				MSCP_LOG_MSG("boardId = %d\n",boardId);
				s_packTimer = CM_LongFromChar(&mData[dataOffset]);
				dataOffset+=4u;
				MSCP_LOG_MSG("s_packTimer = %d\n",s_packTimer);
				s_packFirstRecvTimer = CM_LongFromChar(&mData[dataOffset]);
				dataOffset+=4u;
				MSCP_LOG_MSG("s_packFirstRecvTimer = %d\n",s_packFirstRecvTimer);
				packRestartMode = mData[dataOffset];
				dataOffset+=1u;
				MSCP_LOG_MSG("packRestartMode = %d\n",packRestartMode);
				reboottype = mData[dataOffset];
				dataOffset+=1u;
				MSCP_LOG_MSG("reboottype = %d\n",reboottype);
				packRestartCrc = CM_LongFromChar(&mData[dataOffset]);
				calcCrc1 = CM_Crc32(&mData[3], 12u);
				dataOffset+=4u;
				packCrc = CM_LongFromChar(&mData[dataOffset]);
				calcCrc2 = CM_Crc32(&mData[2], 17);
				dataOffset+=4u;
				/*- crc以及重启方式是否正确并且一次回复到二次请求接收时间是否小于两分钟 */
				if((packRestartCrc != calcCrc1) || (packCrc != calcCrc2))
				{
					/*- 非法包丢弃 */
					packAccredit = 1u;
					reasonAuthorization = 1u;
					MSCP_LOG_MSG("0xa6 error packRestartCrc=%d,calcCrc1=%d,packCrc=%d,calcCrc2=%d\n", \
							packRestartCrc,calcCrc1,packCrc,calcCrc2);

				}
				else if((g_MSCP_SysCount - s_packFirstRecvTimer)*g_RMUP_Cfg.CYC_TIME >= 120000)
				{
					packAccredit = 1u;
					reasonAuthorization = 7u;
					MSCP_LOG_MSG("0xa6 error s_packFirstRecvTimer = %d, g_MSCP_SysCount = %d, cyctime = %d\n", \
												s_packFirstRecvTimer,g_MSCP_SysCount,g_RMUP_Cfg.CYC_TIME);
				}
				else if((0x55u != reboottype) && (0xaau != reboottype))
				{
					packAccredit = 1u;
					reasonAuthorization = 6u;
					MSCP_LOG_MSG("0xa6 illegality:6 reboottype=%d\n",reboottype);
				}
				else if((FAULT_REBOOT_CUT_MAX <= s_FaultRebootCut) &&(0x55u == reboottype))
				{
					/*- 远程-不更新重启-3次禁止故障重启*/
					packAccredit = 1u;
					reasonAuthorization = 4u;
					MSCP_LOG_MSG("0xa6 illegality:4 rebootcut=%d\n",s_FaultRebootCut);
				}
				else
				{
					/*- 2oo2功能是否开启 */
					if (0x55u == g_RMUP_Cfg.M_2oo2_Enable)
					{
						/*- 2oo2 quit */
						(void)SFM_2oo2_Exchange_FullDuplex_Crash(&mData[0], 0, &pData[0], 0u, ENUM_2oo2_SHUTDOWNQUIT);
					}
					else
					{
						/*- 无处理 */
					}
					packAccredit = 0u;
					reasonAuthorization = 0u;
					MSCP_LOG_MSG("0xa6 reboottype = %d\n",reboottype);
				}
	    	}
	    	else
	    	{
	    		/*- 非法包丢弃 */
				(void)CFM_DarkLog_Storage(DARK_LOG_HEX, TSCP_DARK_WARNING, 4U, DARK_FAULT_CODE_MERGE(REMOTE_UPDATE, DARK_FAULT_CODE_FUN_ORDER_8, TSCP_DARK_ASSERT_1));
	    		MSCP_LOG_MSG("error pack packType = %d\n",packType);
	    	}			
		}
		else
		{
			/*- 无处理 */
		}
    }while(0u < dataLen);

    /*- 返回帧类型 */
    return packType;
}
/**
* @brief 远程重启一次确认帧组包发送
*/
static void PFM_DataReastart_Send(void)
{
	/*- 变量初始化 */
	CM_UINT8 mData[1000] = { 0u };
	CM_UINT32 dataOffset = 0u;
	CM_UINT16 packLen = 0u;
	CM_UINT32 calcCrc1 = 0u;
	CM_UINT32 calcCrc2 = 0u;
	CM_UINT8 boardType = 0u;
	CM_UINT8 boardId = 0u;
    /*- 是否允许重启,并且开启了2取功能  */
    if((0x55u == g_RMUP_Cfg.M_2oo2_Enable)&&(2u != packAccredit))
    {

		/*- 首次发送远程重启确认报文  */
		packAccredit = PFM_RmUp_Check();
    	dataOffset = 0u;
    	/* 长度预留 */
    	dataOffset += 2u;
    	mData[dataOffset] = 0x55u;
    	dataOffset += 1u;

    	boardType = 1u;
    	mData[dataOffset] = boardType;
    	dataOffset += 1u;
    	if(1u == g_RMUP_Cfg.BOARD_ID)
    	{
    		boardId = 0xA0u;
    	}
    	else
    	{
    		boardId = 0x0Bu;
    	}
    	mData[dataOffset] = boardId;
    	dataOffset += 1u;
    	s_packFirstSendTimer = g_MSCP_SysCount;
		CM_LongToChar(s_packFirstSendTimer, &mData[dataOffset]);
		dataOffset += 4u;
    	CM_LongToChar(s_packTimer, &mData[dataOffset]);
    	dataOffset += 4u;
    	mData[dataOffset] = packAccredit;
    	dataOffset += 1u;
    	mData[dataOffset] = reasonAuthorization;
    	dataOffset += 1u;
    	calcCrc1 = CM_Crc32(&mData[3], dataOffset - 3u);
    	CM_LongToChar(calcCrc1, &mData[dataOffset]);
    	dataOffset += 4u;

		calcCrc2 = CM_Crc32(&mData[2], dataOffset - 2u);
		CM_LongToChar(calcCrc2, &mData[dataOffset]);
		dataOffset += 4u;
		packLen = dataOffset - 2u;
		CM_ShortToChar(packLen, &mData[0]);
		/*- 发送远程重启确认报文  */
		MSCP_LOG_MSG("shut down dateOffset = %d, packLen = %d\n",dataOffset,packLen);
		(void)Prtcl_InnetSafe_AppRmSend(mData, dataOffset);
    }
    else
    {
    	/*- 无处理 */
    }
}

/**
* @brief 远程重启二次确认帧组包发送
*/
static void PFM_DataReastart_SendTwo(void)
{
	/*- 变量初始化 */
	CM_UINT8 mData[1000] = { 0u };
	CM_UINT32 dataOffset = 0u;
	CM_UINT16 packLen = 0u;
	CM_UINT32 calcCrc1 = 0u;
	CM_UINT32 calcCrc2 = 0u;
	CM_UINT8 boardType = 0u;
	CM_UINT8 boardId = 0u;
    /*- 是否允许重启,并且开启了2取功能  */
    if((0x55u == g_RMUP_Cfg.M_2oo2_Enable)&&(2u != packAccredit))
    {
    	/*- @alias 首次发送远程重启确认报文  */
		if (0u == s_countres)
		{
			packAccredit = PFM_RmUp_Check();
		}
		else
		{

		}

		/*- 解包  */
    	dataOffset = 0u;
    	/* 长度预留 */
    	dataOffset += 2u;
    	mData[dataOffset] = 0x56u;
    	dataOffset += 1u;
    	boardType = 1u;
    	mData[dataOffset] = boardType;
    	dataOffset += 1u;
    	if(1u == g_RMUP_Cfg.BOARD_ID)
    	{
    		boardId = 0xA0u;
    	}
    	else
    	{
    		boardId = 0x0Bu;
    	}
    	mData[dataOffset] = boardId;
    	dataOffset += 1u;
    	CM_LongToChar(g_MSCP_SysCount, &mData[dataOffset]);
    	dataOffset += 4u;
    	CM_LongToChar(s_packTimer, &mData[dataOffset]);
    	dataOffset += 4u;
    	mData[dataOffset] = packAccredit;
    	dataOffset += 1u;
    	mData[dataOffset] = reasonAuthorization;
    	dataOffset += 1u;
    	calcCrc1 = CM_Crc32(&mData[3], dataOffset - 3u);
    	CM_LongToChar(calcCrc1, &mData[dataOffset]);
    	dataOffset += 4u;
		/*- 用来记录远程重启时间 */
		s_countres++;
		calcCrc2 = CM_Crc32(&mData[2], dataOffset - 2u);
		CM_LongToChar(calcCrc2, &mData[dataOffset]);
		dataOffset += 4u;
		packLen = dataOffset - 2u;
		CM_ShortToChar(packLen, &mData[0]);
		/*- 发送远程重启确认报文  */
		MSCP_LOG_MSG("shut down dateOffset = %d, packLen = %d\n",dataOffset,packLen);
		(void)Prtcl_InnetSafe_AppRmSend(mData, dataOffset);
    }
    else
    {
    	/*- 无处理 */
    }
}

/**
* @brief 远程重启处理
*/
static void PFM_DataReastart(void)
{
	/*- 变量初始化  */
	CM_UINT8 packType = 0u;
	static CM_INT32 replycount = 0;
	static CM_UINT8 flag = 0;
	/*- 重启命令接收处理 */
	packType = PFM_DataReastart_Recv();
	/*- 一次重启命令发送处理 */
	if(0xa5 == packType)
	{
		PFM_DataReastart_Send();
		packType = 0u;
	}
	/*- 二次重启命令发送处理 */
	else if(0xa6 == packType)
	{
		PFM_DataReastart_SendTwo();
		replycount = 0;
		flag = 1;
	}
	else
	{
		/*- 如果处理过一次二次重启确认,则在连续发送10次二次确认命令  */
		if((replycount < g_RMUP_Cfg.reboot_replycount) && (1 == flag))
		{
			PFM_DataReastart_SendTwo();
			replycount++;
		}
		else
		{
			/*- 无处理 */
			flag = 0;
			replycount = 0;
			MSCP_LOG_MSG("No restart request was received\n");
		}
	}
}

/**
* @brief 输入数据处理(维护模式)
*/
void PFM_DataProc_Crash(void)
{
	/*- 处理重启请求报文  */
	PFM_DataReastart();

	/*- 发送设备信息报文(设备信息报文必须最后发送)  */
	(void)PFM_DevStateSend(0);
}

/**
* @brief 周期末处理(维护模式)
*/
void PFM_EndProc_Crash(void)
{
	/*- 变量初始化 */
	CM_UINT8 mData[1024*100] = { 0u };
	CM_UINT8 pData[1024*100] = { 0u };

	if (g_RMUP_Cfg.reboot_replycount == s_countres)
	{
		/*- 2oo2功能是否开启 */
	    if (0x55u == g_RMUP_Cfg.M_2oo2_Enable)
	    {
			/*- 2oo2 quit */
			(void)SFM_2oo2_Exchange_FullDuplex_Crash(&mData[0], 0, &pData[0], 0u, ENUM_2oo2_SHUTDOWNQUIT);
	    }
	    else
		{
			/*- 无处理 */
		}
		PFM_RemoteUpdate_Reboot();
	}
	else
	{
		/*- 无处理 */
	}

	SFM_LogRmInPrtcl();
}

/**
* @brief 退出运营模式,进入维护模式
*/
void PFM_MaintenanceMode(void)
{
	CM_UINT64 costlog[10] = {0};
	MSCP_LOG_MSG("g_MSCP_SysCount = %d\n",g_MSCP_SysCount);
	/*- 系统周期号++,用来维持协议 */
	g_MSCP_SysCount++;
	g_PFM_Check = PFM_CFC_PROC_NUM + 1;
	/*- 输入 (进入运营模式,先输入在输出) */
	/*- 维护模式输入微周期处理 */
	costlog[0] = CM_GetTick();
	PFM_InputProc_Crash();
	costlog[1] = CM_GetTick();
	MSCP_LOG_MSG("1 PFM_InputProc_Crash cost = %lld us\n", (costlog[1] - costlog[0]) / 1000u);
	g_PFM_Check = PFM_CFC_PROC_NUM + 5;
	/*- 维护模式协议层解析 */
	SFM_UnPrtclProc_Crash();
	costlog[2] = CM_GetTick();
	MSCP_LOG_MSG("2 SFM_UnPrtclProc_Crash cost = %lld us\n", (costlog[2] - costlog[1]) / 1000u);
	g_PFM_Check = PFM_CFC_PROC_NUM + 9;
	/*- 数据处理 */
	PFM_DataProc_Crash();
	costlog[3] = CM_GetTick();
	MSCP_LOG_MSG("3 PFM_DataProc_Crash cost = %lld us\n", (costlog[3] - costlog[2]) / 1000u);
	g_PFM_Check = PFM_CFC_PROC_NUM + 10;
	/*- 维护模式协议层封装待发送数据  */
	SFM_EnPrtclProc_Crash();
	costlog[4] = CM_GetTick();
	MSCP_LOG_MSG("4 SFM_EnPrtclProc_Crash cost = %lld us\n", (costlog[4] - costlog[3]) / 1000u);
	g_PFM_Check = PFM_CFC_PROC_NUM + 11;
	/*- 维护模式输出微周期处理  */
	PFM_OutputProc_Crash();
	costlog[5] = CM_GetTick();
	MSCP_LOG_MSG("5 PFM_OutputProc_Crash cost = %lld us\n", (costlog[5] - costlog[4]) / 1000u);
	g_PFM_Check = PFM_CFC_PROC_NUM + 12;
	/*- 周期末处理*/
	PFM_EndProc_Crash();
	costlog[6] = CM_GetTick();
	MSCP_LOG_MSG("6 PFM_EndProc_Crash cost = %lld us\n", (costlog[6] - costlog[5]) / 1000u);
	g_PFM_Check = PFM_CFC_PROC_NUM + 13;
}

/**
* @brief 设置维护终端内网id
* @param dstName 维护终端内网id
*/
void PFM_SetMaintenanceId(IN CM_UINT16 dstName )
{
    /*- 变量初始化 */
    CM_INT32 i = 0;
	CM_UINT8 FindFlag = 0u;
    /*- 开始遍历内网通信配置:是否遍历完成:下一条配置 */
    for (i = 1; i <= (CM_INT32)g_PFM_Cfg.INNET_COM_NUM; i++)
    {
        /*- 是否找到了目标内网ID */
        if (dstName == g_PFM_Cfg.INNET_COM_CFG[i].InnetID)
        {
            /*- 设置维护终端内网id */
            g_Maintenance_Id = dstName;
			FindFlag = 1u;
            /*- 返回 */
            break;
        }
        else
        {
            /*- 无处理 */
        }
    }

	if (1u != FindFlag)
	{
		(void)CFM_DarkLog_Storage(DARK_LOG_HEX, TSCP_DARK_WARNING, 4U, DARK_FAULT_CODE_MERGE(REMOTE_UPDATE, DARK_FAULT_CODE_FUN_ORDER_10, TSCP_DARK_ASSERT_1));
		MSCP_LOG_MSG("MSCP_SetMaintenanceId Error!!! dstName not find in INNET_COM_CFG InnetID\n",dstName);
	}
	else
	{

	}
}
/**
* @brief 硬件重启确认帧组包发送
* @param type 发送数据类型 取值范围：0x55或0x56
* @param rcv_packTime 接收请求时间戳 取值范围：0~0xffffffff
* @param accredit 授权状态 取值范围：0~0xff
* @param reason 授权原因 取值范围：0~0xff
* @return 无
*/
static void PFM_HardWareReastart_Send(CM_UINT8 type,CM_UINT32 rcv_packTime,CM_UINT8 accredit,CM_UINT8 reason)
{
	/*- 变量初始化 */
	CM_UINT8 mData[1000] = { 0u };
	CM_UINT32 dataOffset = 0u;
	CM_UINT16 packLen = 0u;
	CM_UINT32 calcCrc1 = 0u;
	CM_UINT32 calcCrc2 = 0u;
	CM_UINT8 ret = 0u;
	/*- 如果数据类型为0x55或0x56 */
	if(0x55u == type || 0x56u == type)
	{
		/* 长度预留 */
		dataOffset += 2u;
		/*帧类型*/
		mData[dataOffset] = type;
		dataOffset += 1u;
		/*板卡类型主机板1*/
		mData[dataOffset] = 1u;
		dataOffset += 1u;
		/*通道ID*/
		if(1u == g_RMUP_Cfg.BOARD_ID)
		{
			mData[dataOffset] = 0xA0u;
		}
		else
		{
			mData[dataOffset] = 0x0Bu;
		}
		dataOffset += 1u;
		/*重启请求命令首次确认时间*/
		s_packFirstSendTimer = g_MSCP_SysCount;
		CM_LongToChar(s_packFirstSendTimer, &mData[dataOffset]);
		dataOffset += 4u;
		MSCP_LOG_MSG("s_packFirstSendTimer = %d\n",s_packFirstSendTimer);
		/*收到的最近一次请求信息中的时间戳 */
		CM_LongToChar(rcv_packTime, &mData[dataOffset]);
		dataOffset += 4u;
		/*授权状态*/
		mData[dataOffset] = accredit;
		dataOffset += 1u;
		/*授权原因*/
		mData[dataOffset] = reason;
		dataOffset += 1u;
		/*CRC*/
		calcCrc1 = CM_Crc32(&mData[3], dataOffset - 3u);
		CM_LongToChar(calcCrc1, &mData[dataOffset]);
		dataOffset += 4u;

		calcCrc2 = CM_Crc32(&mData[2], dataOffset - 2u);
		CM_LongToChar(calcCrc2, &mData[dataOffset]);
		dataOffset += 4u;
		packLen = dataOffset - 2u;
		CM_ShortToChar(packLen, &mData[0]);
		ret = Prtcl_InnetSafe_AppRmSend(mData,dataOffset);
		if(ret == 0)
		{
			/*输出异常警告*/
			(void)CFM_DarkLog_Storage(DARK_LOG_HEX, TSCP_DARK_WARNING, 4U, DARK_FAULT_CODE_MERGE(REMOTE_UPDATE, DARK_FAULT_CODE_FUN_ORDER_11, TSCP_DARK_ASSERT_1));
			MSCP_LOG_MSG("IO OutPut Type 0x%x ERR!!!\n",type);
		}
	}
	else
	{
		(void)CFM_DarkLog_Storage(DARK_LOG_HEX, TSCP_DARK_WARNING, 4U, DARK_FAULT_CODE_MERGE(REMOTE_UPDATE, DARK_FAULT_CODE_FUN_ORDER_11, TSCP_DARK_ASSERT_2));
		/*- 类型错误无处理*/
	}
}

/**
* @brief 远程切系确认帧组包发送
* @param type 发送数据类型 取值范围：0x55或0x56
* @param rcv_packTime 接收请求时间戳 取值范围：0~0xffffffff
* @param accredit 授权状态 取值范围：0~0xff
* @param reason 授权原因 取值范围：0~0xff
* @return 无
*/
static void PFM_RemoteSwitch_Send(CM_UINT8 type,CM_UINT32 rcv_packTime,CM_UINT8 accredit,CM_UINT8 reason)
{
	/*- 变量初始化 */
	CM_UINT8 mData[1000] = { 0u };
	CM_UINT32 dataOffset = 0u;
	CM_UINT16 packLen = 0u;
	CM_UINT32 calcCrc1 = 0u;
	CM_UINT32 calcCrc2 = 0u;
	CM_UINT8 ret = 0u;
	/*- 如果数据类型为0x57或0x58 */
	if(0x57u == type || 0x58u == type)
	{
		/* 长度预留 */
		dataOffset += 2u;
		/*帧类型*/
		mData[dataOffset] = type;
		dataOffset += 1u;
		/*板卡类型主机板1*/
		mData[dataOffset] = 1u;
		dataOffset += 1u;
		/*通道ID*/
		if(1u == g_RMUP_Cfg.BOARD_ID)
		{
			mData[dataOffset] = 0xA0u;
		}
		else
		{
			mData[dataOffset] = 0x0Bu;
		}
		dataOffset += 1u;
		/*重启请求命令首次确认时间*/
		s_packFirstSendTimer = g_MSCP_SysCount;
		CM_LongToChar(s_packFirstSendTimer, &mData[dataOffset]);
		dataOffset += 4u;
		/*收到的最近一次请求信息中的时间戳 */
		CM_LongToChar(rcv_packTime, &mData[dataOffset]);
		dataOffset += 4u;
		/*授权状态*/
		mData[dataOffset] = accredit;
		dataOffset += 1u;
		/*授权原因*/
		mData[dataOffset] = reason;
		dataOffset += 1u;
		/*CRC*/
		calcCrc1 = CM_Crc32(&mData[3], dataOffset - 3u);
		CM_LongToChar(calcCrc1, &mData[dataOffset]);
		dataOffset += 4u;

		calcCrc2 = CM_Crc32(&mData[2], dataOffset - 2u);
		CM_LongToChar(calcCrc2, &mData[dataOffset]);
		dataOffset += 4u;
		packLen = dataOffset - 2u;
		CM_ShortToChar(packLen, &mData[0]);
		ret = Prtcl_InnetSafe_AppRmSend(mData,dataOffset);
		if(ret == 0)
		{
			/*输出异常警告*/
			(void)CFM_DarkLog_Storage(DARK_LOG_HEX, TSCP_DARK_WARNING, 4U, DARK_FAULT_CODE_MERGE(REMOTE_UPDATE, DARK_FAULT_CODE_FUN_ORDER_12, TSCP_DARK_ASSERT_1));
			MSCP_LOG_MSG("Switch OutPut Type 0x%x ERR!!!\n",type);
		}
	}
	else
	{
		/*- 类型错误无处理*/
		(void)CFM_DarkLog_Storage(DARK_LOG_HEX, TSCP_DARK_WARNING, 4U, DARK_FAULT_CODE_MERGE(REMOTE_UPDATE, DARK_FAULT_CODE_FUN_ORDER_12, TSCP_DARK_ASSERT_2));
	}
}

/**
* @brief 远程硬件重启命令接收处理
* @param *mData 接收原始数据 取值范围：非空
* @param  dataOffset 当前数据偏移量 取值范围：0~0xffffffff
* @param  packLen 帧长度 取值范围：0~0xffff
* @param  packType 帧类型 取值范围：0~0xff
*/
static void PFM_Data_HardWareReastart(CM_UINT8* mData,CM_UINT32 dataOffset,CM_UINT16 packLen,CM_UINT8 packType)
{
	/*- 变量初始化 */
	CM_UINT32 packTimer = 0u;
	CM_UINT32 packCrc = 0u;
	CM_UINT32 calcCrc1 = 0u;
	CM_UINT32 calcCrc2 = 0u;
	CM_UINT8 packRestartMode = 0u; /*重启方式*/
	CM_UINT8 boardType = 0u;
	CM_UINT8 boardId = 0u;
	CM_UINT32 packRestartCrc = 0u; /*重启请求命令crc*/
	CM_UINT8 boottype = 0u;/**<临时 重启请求命令  0x55:未更新重启  0xaa:升级重启 0xd1~d7:硬重启 */
	static CM_UINT8 s_boottype = 0u;/**<静态 重启请求命令  0x55:未更新重启  0xaa:升级重启 ,0xd1~d7:硬重启 */
	CM_UINT8 recvType = 0u;
	ENUM_2x2_STATE_T localState = SFM_2x2_GetLocal2x2State();
	/*- 如果帧类型是一次请求确认 */
	if(0xa5u == packType)
	{
		/*- 按照一次请求确认帧继续解包 */
		boardType = mData[dataOffset];
		dataOffset +=1u;
		MSCP_LOG_MSG("boardType = %d\n",boardType);
		boardId = mData[dataOffset];
		dataOffset +=1u;
		MSCP_LOG_MSG("boardId = %d\n",boardId);
		packTimer = CM_LongFromChar(&mData[dataOffset]);
		dataOffset+=4u;
		MSCP_LOG_MSG("packTimer = %d\n",packTimer);
		packRestartMode = mData[dataOffset];
		dataOffset+=1u;
		MSCP_LOG_MSG("packRestartMode = %d\n",packRestartMode);
		boottype = mData[dataOffset];
		dataOffset+=1u;
		MSCP_LOG_MSG("boottype = %d\n",boottype);
		packRestartCrc = CM_LongFromChar(&mData[dataOffset]);
		calcCrc1 = CM_Crc32(&mData[3], 8u);
		dataOffset+=4u;
		packCrc = CM_LongFromChar(&mData[dataOffset]);
		calcCrc2 = CM_Crc32(&mData[2], 13u);
		dataOffset+=4u;
		/*- crc以及重启方式是否正确 */
		if((packRestartCrc != calcCrc1) || (packCrc != calcCrc2))
		{
			/*- 非法包丢弃 */
			s_boottype = 0u;
			s_HardReboottype = 0u;
			s_packHardAccredit = 1u;
			s_reasonHardAuthorization = 1u;
			(void)CFM_DarkLog_Storage(DARK_LOG_HEX, TSCP_DARK_WARNING, 4U, DARK_FAULT_CODE_MERGE(REMOTE_UPDATE, DARK_FAULT_CODE_FUN_ORDER_13, TSCP_DARK_ASSERT_1));
			MSCP_LOG_MSG("error pack 0xa5 packRestartCrc=%d,calcCrc1=%d,packCrc=%d,calcCrc2=%d,reboottype=%d\n",packRestartCrc,calcCrc1,packCrc,calcCrc2,boottype);
		}
		else if((0x55 == s_switch2xFlag) || (0x55 == s_switchRmFlag) || (1 == g_iostate))
		{
			/*- 非法包丢弃 */
			s_boottype = 0u;
			/* s_HardReboottype = 0u; */
			s_packHardAccredit = 1u;
			s_reasonHardAuthorization = 5u;
			MSCP_LOG_MSG("error pack 0xa5,s_switch2xFlag=%d,s_switchRmFlag=%d,g_iostate=%d\n" \
					,s_switch2xFlag,s_switchRmFlag,g_iostate);
		}
		else if(((boottype <= 0xd0u) || (boottype >= 0xd8u )) || \
				((0xd3 == boottype) && (NULL == p_Serial_Id_Func)))
		{
			/*- 非法包丢弃 */
			s_boottype = 0u;
			s_HardReboottype = 0u;
			s_packHardAccredit = 1u;
			s_reasonHardAuthorization = 6u;
			(void)CFM_DarkLog_Storage(DARK_LOG_HEX, TSCP_DARK_WARNING, 4U, DARK_FAULT_CODE_MERGE(REMOTE_UPDATE, DARK_FAULT_CODE_FUN_ORDER_13, TSCP_DARK_ASSERT_2));
			MSCP_LOG_MSG("error pack 0xa5 boottype=%d\n",boottype);
		}
		else if((ENUM_2x2_SLAVE == localState) && ((boottype == 0xd1) || (boottype == 0xd7)))
		{
			/*- 非法包丢弃 */
			s_boottype = 0u;
			s_HardReboottype = 0u;
			s_packHardAccredit = 1u;
			s_reasonHardAuthorization = 7u;
			(void)CFM_DarkLog_Storage(DARK_LOG_HEX, TSCP_DARK_WARNING, 4U, DARK_FAULT_CODE_MERGE(REMOTE_UPDATE, DARK_FAULT_CODE_FUN_ORDER_13, TSCP_DARK_ASSERT_3));
			MSCP_LOG_MSG("error pack 0xa5 boottype=%d,localState=%d\n",boottype,localState);
		}
		else
		{
			s_boottype = boottype;
			s_packHardAccredit = 0u;
			s_reasonHardAuthorization = 0u;
			MSCP_LOG_MSG("0xa5 boottype = %d\n",boottype);
		}
		/*首次应答*/
		recvType = 0x55u;
	}
	/*- 如果帧类型是二次请求确认 */
	else
	{
		/*- 按照二次请求确认帧继续解包 */
		boardType = mData[dataOffset];
		dataOffset +=1u;
		MSCP_LOG_MSG("boardType = %d\n",boardType);
		boardId = mData[dataOffset];
		dataOffset +=1u;
		MSCP_LOG_MSG("boardId = %d\n",boardId);
		packTimer = CM_LongFromChar(&mData[dataOffset]);
		dataOffset+=4u;
		MSCP_LOG_MSG("packTimer = %d\n",packTimer);
		s_packFirstRecvTimer = CM_LongFromChar(&mData[dataOffset]);
		dataOffset+=4u;
		MSCP_LOG_MSG("s_packFirstRecvTimer = %d\n",s_packFirstRecvTimer);
		packRestartMode = mData[dataOffset];
		dataOffset+=1u;
		MSCP_LOG_MSG("packRestartMode = %d\n",packRestartMode);
		boottype = mData[dataOffset];
		dataOffset+=1u;
		MSCP_LOG_MSG("boottype = %d\n",boottype);
		packRestartCrc = CM_LongFromChar(&mData[dataOffset]);
		calcCrc1 = CM_Crc32(&mData[3], 12u);
		dataOffset+=4u;
		packCrc = CM_LongFromChar(&mData[dataOffset]);
		calcCrc2 = CM_Crc32(&mData[2], 17u);
		dataOffset+=4u;
		/*- crc计算是否正确 */
		if((packRestartCrc != calcCrc1) || (packCrc != calcCrc2))
		{
			/*- crc计算失败丢弃错误包  */
			s_boottype = 0u;
			s_HardReboottype = 0u;
			s_packHardAccredit = 1u;
			s_reasonHardAuthorization = 1u;
			MSCP_LOG_MSG("error pack 0xa6 packSwitchCrc=%d,calcCrc1=%d,packCrc=%d,calcCrc2=%d\n",packRestartCrc,calcCrc1,packCrc,calcCrc2);
			(void)CFM_DarkLog_Storage(DARK_LOG_HEX, TSCP_DARK_WARNING, 4U, DARK_FAULT_CODE_MERGE(REMOTE_UPDATE, DARK_FAULT_CODE_FUN_ORDER_13, TSCP_DARK_ASSERT_4));
		}
		/*- 是否正在执行其它命令  */
		else if((0x55 == s_switch2xFlag) || (0x55 == s_switchRmFlag) || (1 == g_iostate))
		{
			/*- 正在执行其它命令  */
			s_boottype = 0u;
			/* s_HardReboottype = 0u; */
			s_packHardAccredit = 1u;
			s_reasonHardAuthorization = 5u;
			MSCP_LOG_MSG("error pack 0xa6,s_switch2xFlag=%d,s_switchRmFlag=%d,g_iostate=%d\n" \
					,s_switch2xFlag,s_switchRmFlag,g_iostate);
			(void)CFM_DarkLog_Storage(DARK_LOG_HEX, TSCP_DARK_WARNING, 4U, DARK_FAULT_CODE_MERGE(REMOTE_UPDATE, DARK_FAULT_CODE_FUN_ORDER_13, TSCP_DARK_ASSERT_5));
		}
		/*- 切系命令一次回复到二次请求接收时间是否小于两分钟 */
		else if(((g_MSCP_SysCount - s_packFirstRecvTimer)*g_RMUP_Cfg.CYC_TIME) >= 120000u)
		{
			s_boottype = 0u;
			s_HardReboottype = 0u;
			s_packHardAccredit = 1u;
			s_reasonHardAuthorization = 7u;
			MSCP_LOG_MSG("error pack 0xa6 g_MSCP_SysCount = %d s_packFirstRecvTimer = %d\n", g_MSCP_SysCount, s_packFirstRecvTimer);
			(void)CFM_DarkLog_Storage(DARK_LOG_HEX, TSCP_DARK_WARNING, 4U, DARK_FAULT_CODE_MERGE(REMOTE_UPDATE, DARK_FAULT_CODE_FUN_ORDER_13, TSCP_DARK_ASSERT_6));
		}
		else if((boottype <= 0xd0u) || (boottype >= 0xd8u ) || (s_boottype != boottype))
		{
			s_boottype = 0u;
			s_HardReboottype = 0u;
			s_packHardAccredit = 1u;
			s_reasonHardAuthorization = 6u;
			MSCP_LOG_MSG("error pack 0xa6 s_boottype = %d boottype = %d\n", s_boottype, boottype);
			(void)CFM_DarkLog_Storage(DARK_LOG_HEX, TSCP_DARK_WARNING, 4U, DARK_FAULT_CODE_MERGE(REMOTE_UPDATE, DARK_FAULT_CODE_FUN_ORDER_13, TSCP_DARK_ASSERT_7));
		}
		else
		{
			s_HardReboottype = s_boottype;
			s_packHardAccredit = 0u;
			s_reasonHardAuthorization = 0u;
			g_iostate = 0x1u;
			MSCP_LOG_MSG("0xa6 boottype = %d, s_boottype = %d\n",boottype, s_boottype);
		}
		/*再次应答*/
		recvType = 0x56u;
	}

	/*- 硬重启命令请求回复 */
	PFM_HardWareReastart_Send(recvType,packTimer,s_packHardAccredit,s_reasonHardAuthorization);
}

/**
* @brief 远程切系命令接收处理
* @param *mData 接收原始数据 取值范围：非空
* @param  dataOffset 当前数据偏移量 取值范围：0~0xffffffff
* @param  packLen 帧长度 取值范围：0~0xffff
* @param  packType 帧类型 取值范围：0~0xff
*/
static void PFM_Data_RemoteSwitch(CM_UINT8* mData,CM_UINT32 dataOffset,CM_UINT16 packLen,CM_UINT8 packType)
{
	/*- 变量初始化 */
	CM_UINT32 packTimer = 0u;
	CM_UINT32 packCrc = 0u;
	CM_UINT32 calcCrc1 = 0u;
	CM_UINT32 calcCrc2 = 0u;
	CM_UINT8 packSwitchMode = 0u; /*切系方式*/
	CM_UINT8 boardType = 0u;
	CM_UINT8 boardId = 0u;
	CM_UINT32 packSwitchCrc = 0u; /*重启请求命令crc*/
	CM_UINT8 recvType = 0u;
	ENUM_2x2_STATE_T localState = SFM_2x2_GetLocal2x2State();
	ENUM_2x2_STATE_T partnerState = SFM_2x2_GetPartner2x2State();
	static ENUM_2x2_STATE_T s_firstState = ENUM_2x2_SHUTDOWN;

	/*- 如果帧类型是一次请求确认 */
	if(0xa7u == packType)
	{
		/*- 按照一次请求确认帧继续解包 */
		boardType = mData[dataOffset];
		dataOffset +=1u;
		MSCP_LOG_MSG("boardType = %d\n",boardType);
		boardId = mData[dataOffset];
		dataOffset +=1u;
		MSCP_LOG_MSG("boardId = %d\n",boardId);
		packTimer = CM_LongFromChar(&mData[dataOffset]);
		dataOffset+=4u;
		MSCP_LOG_MSG("packTimer = %d\n",packTimer);
		packSwitchMode = mData[dataOffset];
		dataOffset+=1u;
		MSCP_LOG_MSG("packSwitchMode = %d\n",packSwitchMode);
		/*- 预留1字节 */
		dataOffset+=1u;
		packSwitchCrc = CM_LongFromChar(&mData[dataOffset]);
		calcCrc1 = CM_Crc32(&mData[3], 8u);
		dataOffset+=4u;
		packCrc = CM_LongFromChar(&mData[dataOffset]);
		calcCrc2 = CM_Crc32(&mData[2], 13u);
		dataOffset+=4u;
		/*- crc以及切换条件是否正确 */
		if((packSwitchCrc != calcCrc1) || (packCrc != calcCrc2))
		{
			/*- crc计算失败丢弃错误包  */
			s_packSwitchAccredit = 1u;
			s_switchAuthorization = 1u;
			MSCP_LOG_MSG("error pack 0xa7 packSwitchCrc=%d,calcCrc1=%d,packCrc=%d,calcCrc2=%d\n",packSwitchCrc,calcCrc1,packCrc,calcCrc2);
			(void)CFM_DarkLog_Storage(DARK_LOG_HEX, TSCP_DARK_WARNING, 4U, DARK_FAULT_CODE_MERGE(REMOTE_UPDATE, DARK_FAULT_CODE_FUN_ORDER_14, TSCP_DARK_ASSERT_1));
		}
		/*- 是否正在执行其它命令  */
		else if( (0x55 == s_switch2xFlag) || (0x55 == s_switchRmFlag) || (1 == g_iostate) || (1 == DFM_switchButton()))
		{
			/*- 正在执行其它命令  */
			s_packSwitchAccredit = 1u;
			s_switchAuthorization = 3u;
			MSCP_LOG_MSG("error pack 0xa7,s_switch2xFlag=%d,s_switchRmFlag=%d,g_iostate=%d\n" \
					,s_switch2xFlag,s_switchRmFlag,g_iostate);
			(void)CFM_DarkLog_Storage(DARK_LOG_HEX, TSCP_DARK_WARNING, 4U, DARK_FAULT_CODE_MERGE(REMOTE_UPDATE, DARK_FAULT_CODE_FUN_ORDER_14, TSCP_DARK_ASSERT_2));
		}
		else if(((localState + partnerState) != (ENUM_2x2_SLAVE + ENUM_2x2_MASTER)) || (1u == SFM_2x2_Get_LeastDoubleCom_State()))
		{
			/*- 切系状态未满足切系条件丢弃错误包  */
			s_packSwitchAccredit = 1u;
			s_switchAuthorization = 2u;
			MSCP_LOG_MSG("error pack 0xa7 localState = %d partnerState = %d\n", localState, partnerState);
			(void)CFM_DarkLog_Storage(DARK_LOG_HEX, TSCP_DARK_WARNING, 4U, DARK_FAULT_CODE_MERGE(REMOTE_UPDATE, DARK_FAULT_CODE_FUN_ORDER_14, TSCP_DARK_ASSERT_3));
		}
		else
		{
			s_packSwitchAccredit = 0u;
			s_switchAuthorization = 0u;
			s_firstState = SFM_2x2_GetLocal2x2State();
		}
		/*首次应答*/
		recvType = 0x57u;
	}
	/*- 如果帧类型是二次请求确认 */
	else
	{
		/*- 按照二次请求确认帧继续解包 */
		boardType = mData[dataOffset];
		dataOffset +=1u;
		MSCP_LOG_MSG("boardType = %d\n",boardType);
		boardId = mData[dataOffset];
		dataOffset +=1u;
		MSCP_LOG_MSG("boardId = %d\n",boardId);
		packTimer = CM_LongFromChar(&mData[dataOffset]);
		dataOffset+=4u;
		MSCP_LOG_MSG("packTimer = %d\n",packTimer);
		s_packFirstRecvTimer = CM_LongFromChar(&mData[dataOffset]);
		dataOffset+=4u;
		MSCP_LOG_MSG("s_packFirstRecvTimer = %d\n",s_packFirstRecvTimer);
		packSwitchMode = mData[dataOffset];
		dataOffset+=1u;
		MSCP_LOG_MSG("packSwitchMode = %d\n",packSwitchMode);
		/*- 预留1字节 */
		dataOffset+=1u;
		packSwitchCrc = CM_LongFromChar(&mData[dataOffset]);
		calcCrc1 = CM_Crc32(&mData[3], 12u);
		dataOffset+=4u;
		packCrc = CM_LongFromChar(&mData[dataOffset]);
		calcCrc2 = CM_Crc32(&mData[2], 17u);
		dataOffset+=4u;
		/*- crc计算是否正确 */
		if((packSwitchCrc != calcCrc1) || (packCrc != calcCrc2))
		{
			/*- crc计算失败丢弃错误包  */
			s_packSwitchAccredit = 1u;
			s_switchAuthorization = 1u;
			MSCP_LOG_MSG("error pack 0xa8 packSwitchCrc=%d,calcCrc1=%d,packCrc=%d,calcCrc2=%d\n",packSwitchCrc,calcCrc1,packCrc,calcCrc2);
			(void)CFM_DarkLog_Storage(DARK_LOG_HEX, TSCP_DARK_WARNING, 4U, DARK_FAULT_CODE_MERGE(REMOTE_UPDATE, DARK_FAULT_CODE_FUN_ORDER_14, TSCP_DARK_ASSERT_4));
		}
		/*- 是否正在执行其它命令  */
		else if((0x55 == s_switch2xFlag) || (0x55 == s_switchRmFlag) || (1 == g_iostate)|| (1 == DFM_switchButton()))
		{
			/*- 正在执行其它命令  */
			s_packSwitchAccredit = 1u;
			s_switchAuthorization = 3u;
			MSCP_LOG_MSG("error pack 0xa8,s_switch2xFlag=%d,s_switchRmFlag=%d,g_iostate=%d\n" \
					,s_switch2xFlag,s_switchRmFlag,g_iostate);
			(void)CFM_DarkLog_Storage(DARK_LOG_HEX, TSCP_DARK_WARNING, 4U, DARK_FAULT_CODE_MERGE(REMOTE_UPDATE, DARK_FAULT_CODE_FUN_ORDER_14, TSCP_DARK_ASSERT_5));
		}
		/*- 切系命令一次回复到二次请求接收时间是否小于两分钟 */
		else if(((g_MSCP_SysCount - s_packFirstRecvTimer)*g_RMUP_Cfg.CYC_TIME) >= 120000u)
		{
			/*- 切系状态未满足切系条件丢弃错误包  */
			s_packSwitchAccredit = 1u;
			s_switchAuthorization = 4u;
			MSCP_LOG_MSG("error pack 0xa8 g_MSCP_SysCount = %d s_packFirstRecvTimer = %d\n", g_MSCP_SysCount, s_packFirstRecvTimer);
			(void)CFM_DarkLog_Storage(DARK_LOG_HEX, TSCP_DARK_WARNING, 4U, DARK_FAULT_CODE_MERGE(REMOTE_UPDATE, DARK_FAULT_CODE_FUN_ORDER_14, TSCP_DARK_ASSERT_6));
		}
		else if(s_firstState != localState)
		{
			/**
				一次请求 主备 同意
				一次请求 主离线 主备状态不一致 返回失败
				一次请求 刚切完系 离线 备
				一次请求：无论如何 状态不一致不允许
				二次请求 主备 因手动切系和一次请求时的主备状态不同。一次确认的时候主回失败，备回正确 (备回正确，兼容网络延迟导致的一次切系主先收到切系命令并且执行)
				二次请求 主离线 离线放，一次主回失败，一次时候得备回允许(兼容网络延迟 同上)
				二次请求 备离线 同上
			*/
			if(ENUM_2x2_MASTER == s_firstState)
			{
				/*- 而此请求热备状态不一致  */
				s_packSwitchAccredit = 1u;
				s_switchAuthorization = 5u;
				MSCP_LOG_MSG("1error pack 0xa8 s_firstState = %d localState = %d\n", s_firstState, localState);
				(void)CFM_DarkLog_Storage(DARK_LOG_HEX, TSCP_DARK_WARNING, 4U, DARK_FAULT_CODE_MERGE(REMOTE_UPDATE, DARK_FAULT_CODE_FUN_ORDER_14, TSCP_DARK_ASSERT_7));
			}
			else
			{
				s_packSwitchAccredit = 0u;
				s_switchAuthorization = 0u;
				MSCP_LOG_MSG("2error pack 0xa8 s_firstState = %d localState = %d\n", s_firstState, localState);
				(void)CFM_DarkLog_Storage(DARK_LOG_HEX, TSCP_DARK_WARNING, 4U, DARK_FAULT_CODE_MERGE(REMOTE_UPDATE, DARK_FAULT_CODE_FUN_ORDER_14, TSCP_DARK_ASSERT_8));
			}
		}
		/*- 切换条件是否正确 */
		else if(((localState + partnerState) != (ENUM_2x2_SLAVE + ENUM_2x2_MASTER)) || (1u == SFM_2x2_Get_LeastDoubleCom_State()))
		{
			/*- 切系状态未满足切系条件丢弃错误包  */
			s_packSwitchAccredit = 1u;
			s_switchAuthorization = 2u;
			MSCP_LOG_MSG("error pack 0xa8 localState = %d partnerState = %d\n", localState, partnerState);
			(void)CFM_DarkLog_Storage(DARK_LOG_HEX, TSCP_DARK_WARNING, 4U, DARK_FAULT_CODE_MERGE(REMOTE_UPDATE, DARK_FAULT_CODE_FUN_ORDER_14, TSCP_DARK_ASSERT_9));
		}
		else if(s_packFirstRecvTimer != s_packFirstSendTimer)
		{
			s_packSwitchAccredit = 1u;
			s_switchAuthorization = 12u;
			MSCP_LOG_MSG("error pack 0xa8 s_firstTimer = %d packTimer = %d\n", s_packFirstSendTimer, s_packFirstRecvTimer);
			(void)CFM_DarkLog_Storage(DARK_LOG_HEX, TSCP_DARK_WARNING, 4U, DARK_FAULT_CODE_MERGE(REMOTE_UPDATE, DARK_FAULT_CODE_FUN_ORDER_14, TSCP_DARK_ASSERT_10));
		}
		else
		{
			/*- 二次至切系状态状态 */
			s_switchRmFlag = 0x55u;
			s_packSwitchAccredit = 0u;
			s_switchAuthorization = 0u;
			s_firstState = ENUM_2x2_SHUTDOWN;
		}
		/*再次应答*/
		recvType = 0x58u;
	}
	/*- 切系命令请求回复 */
	PFM_RemoteSwitch_Send(recvType,packTimer,s_packSwitchAccredit,s_switchAuthorization);
}


/**
* @brief 远程硬件重启\切系命令接收处理
* @param *mData 接收原始数据 取值范围：非空
* @param dataLen 数据长度 取值范围：0~0xffffffff
* @return 帧类型
* - 0xa5首次重启请求
* - 0xa6二次重启请求
* - 0xa7首次切系请求
* - 0xa8二次切系请求
*/
CM_UINT8 PFM_RemoteRun_Data(CM_UINT8 *mData,CM_UINT32 dataLen)
{
	/*- 变量初始化 */
	CM_UINT32 dataOffset = 0u;
	CM_UINT16 packLen = 0u;
	CM_UINT8 packType = 0u;
	/*- 如果收到了数据并且入参不为空 */
	if ((0u < dataLen) && (NULL != mData))
	{
		/*- 解包 */
		MSCP_LOG_MSG("PFM_DataProc_Crash dataLen = %d\n",dataLen);
		packLen = CM_ShortFromChar(&mData[0]);
		dataOffset += 2u;
		packType = mData[dataOffset];
		dataOffset +=1u;
		/*- 如果在运行模式，进入硬件重启模式*/
		if(ENUM_BOARDSTATE_RUN == PFM_GetBoardState())
		{
			if((0xA5u == packType) || (0xA6u == packType))
			{
				PFM_Data_HardWareReastart(mData,dataOffset,packLen,packType);
			}
			else if((0xA7u == packType) || (0xA8u == packType))
			{
				PFM_Data_RemoteSwitch(mData,dataOffset,packLen,packType);
			}
			else
			{
				/*- 无处理 */
			}
		}
		else
		{
			/*- 非运行模式无处理 */
		}
	}
	else
	{
		/*- 无处理 */
		(void)CFM_DarkLog_Storage(DARK_LOG_HEX, TSCP_DARK_WARNING, 4U, DARK_FAULT_CODE_MERGE(REMOTE_UPDATE, DARK_FAULT_CODE_FUN_ORDER_15, TSCP_DARK_ASSERT_1));
	}

    /*- 返回帧类型 */
    return packType;
}

/**
* @brief 硬件重启IO更新
*/
void PFM_HardWareBoot_UpData(void)
{
	/*- 更新板卡状态 */
	g_boardState = g_AppSetboardState;
	/*- 更新硬重启模式 */
	reboottype = s_HardReboottype;
	MSCP_LOG_MSG("reboottype = %d, s_HardReboottype = %d\n",reboottype,s_HardReboottype);
	/*- 更新切系状态 */
	if(0x55 == s_switchRmFlag)
	{
		SFM_2x2_Enable_AIDSwitchStart();
	}
	else
	{
		/*- 无处理 */
	}
	s_switch2xFlag = SFM_2x2_Get_AIDSwitchStart();
	if(0u == s_HardReboottype)
	{
		g_iostate = 0u;
	}
	s_switchRmFlag = 0xaau;
}

/**
* @brief 执行硬件重启IO输出
* - 执行重启命令过程中禁止任何形式的切系
*/
void PFM_HardWareBoot_OutPut(void)
{
	/*- 变量初始化 */
	CM_INT32 ret = 0;
	CM_UINT8 type = 0u;
	static ENUM_HARDWARE_BOOT_SELFCHECK_T checkselfret = ENUM_RELAY_1ST_OUTPUT;
	/*- 重启命令为硬重启命令 */
	if((0xd0u < reboottype) && (0xd8u > reboottype))
	{
		type = reboottype;
		/*- @alias 执行硬重启  */
		switch(type)
		{
			case 0xd1:
				/*- 1100:PUB&IOB*/
				if(ENUM_2x2_MASTER == SFM_2x2_GetLocal2x2State())
				{
					MSCP_LOG_MSG("PFM_HardWareBoot_OutPut 1\n");
					checkselfret = PFM_HardWareBoot_CheckSelf(0x0Cu,ENUM_TYPE_PUB,type);
				}
				else
				{
					MSCP_LOG_MSG("PFM_HardWareBoot_OutPut 2\n");
					checkselfret = ENUM_RELAY_1ST_OUTPUT;
					MSCP_LOG_MSG("Is Not Master:0x%x,No Execute!!!\n",type);
				}
				break;
			case 0xd2:
				/*- 1010:CCU*/
				MSCP_LOG_MSG("PFM_HardWareBoot_OutPut 3\n");
				checkselfret = PFM_HardWareBoot_CheckSelf(0x0Au,ENUM_TYPE_CCU,type);
				break;
			case 0xd3:
				/*- 0110:SEB*/
				MSCP_LOG_MSG("PFM_HardWareBoot_OutPut 4\n");
				checkselfret = PFM_HardWareBoot_CheckSelf(0x06u,ENUM_TYPE_SEB,type);
				break;
			case 0xd4:
				/*- 1001:ESB*/
				MSCP_LOG_MSG("PFM_HardWareBoot_OutPut 5\n");
				checkselfret = PFM_HardWareBoot_CheckSelf(0x09u,ENUM_TYPE_ESB,type);
				break;
			case 0xd5:
				/*- 0101:EEB*/
				MSCP_LOG_MSG("PFM_HardWareBoot_OutPut 6\n");
				checkselfret = PFM_HardWareBoot_CheckSelf(0x05u,ENUM_TYPE_OTHER,type);
				break;
			case 0xd6:
				/*- 0011:OCIO预留，硬件不支持禁止打开*/
				/*ret = DFM_SetIO_OutPut(0x03);*/
				MSCP_LOG_MSG("PFM_HardWareBoot_OutPut 7\n");
				checkselfret = ENUM_RELAY_1ST_OUTPUT;
				break;
			case 0xd7:
				/*- 1111:ALL*/
				MSCP_LOG_MSG("PFM_HardWareBoot_OutPut 8\n");
				if(ENUM_2x2_MASTER == SFM_2x2_GetLocal2x2State())
				{
					MSCP_LOG_MSG("PFM_HardWareBoot_OutPut 9\n");
					checkselfret = PFM_HardWareBoot_CheckSelf(0x0Fu,ENUM_TYPE_ALL,type);
				}
				else
				{
					MSCP_LOG_MSG("PFM_HardWareBoot_OutPut 10\n");
					checkselfret = ENUM_RELAY_1ST_OUTPUT;
					MSCP_LOG_MSG("Is Not Master:0x%x,No Execute!!!\n",type);
				}
				break;
			default:
				MSCP_LOG_MSG("PFM_HardWareBoot_OutPut 11\n");
				checkselfret = ENUM_RELAY_1ST_OUTPUT;
				ret = -1;
				break;
		}
		MSCP_LOG_MSG("IO OutPut Type 0x%x!!!\n",type);
		if(ENUM_RELAY_1ST_OUTPUT == checkselfret)
		{
			MSCP_LOG_MSG("PFM_HardWareBoot_OutPut 12\n");
			/*- 恢复运营状态*/
			reboottype = 0u;
			s_HardReboottype = 0u;
			g_iostate = 0x0u;
		}
	}
	else
	{
		MSCP_LOG_MSG("PFM_HardWareBoot_OutPut 13\n");
	}
	if(ret != 0)
	{
		/*- 输出异常警告*/
		MSCP_LOG_MSG("IO OutPut Type 0x%x ERR!!!\n",type);
		(void)CFM_DarkLog_Storage(DARK_LOG_HEX, TSCP_DARK_WARNING, 4U, DARK_FAULT_CODE_MERGE(REMOTE_UPDATE, DARK_FAULT_CODE_FUN_ORDER_16, TSCP_DARK_ASSERT_1));
	}
}

/**
* @brief 硬重启自检状态机
* @param level 待输出IO 取值范围：0x00~0x0F
* @param board_type 当前命令目标重启板卡类型 取值范围：1~5
* @param reboottype 重启命令类型 取值范围：0xD1~0xD7
* @return ENUM_HARDWARE_BOOT_SELFCHECK_T 当前检测步骤 取值范围：0~11
*/
ENUM_HARDWARE_BOOT_SELFCHECK_T PFM_HardWareBoot_CheckSelf(CM_UINT8 level,ENUM_BOARD_TYPE_T board_type,CM_UINT8 reboottype)
{
	/*- 变量初始化 */
	static ENUM_HARDWARE_BOOT_SELFCHECK_T s_selfcheck_state = ENUM_RELAY_1ST_OUTPUT;
	static CM_UINT32 s_OutPutTime = 0u;	/* 继电器输出时间 */
	static CM_UINT8 s_boot_result = 0xAAu;/* 重启结果 */
	static CM_UINT8 s_relay_default[4] = {0x55u,0x55u,0x55u,0x55u};/* 继电器故障记录 */
	static CM_UINT8 s_ComState[4] = {0u,0u,0u,0u};/* 继电器故障记录 */
	CM_UINT8 comResult = 0;
	/*- 如果无需输出io */
	if(0u == level)
	{
		/*- 状态机恢复 */
		s_selfcheck_state = ENUM_RELAY_1ST_OUTPUT;
		s_OutPutTime = 0u;
		s_WaitTime = 0u;
		s_boot_result = 0xAAu;
		s_relay_default[0] = 0x55u;
		s_relay_default[1] = 0x55u;
		s_relay_default[2] = 0x55u;
		s_relay_default[3] = 0x55u;
		s_ComState[0] = 0u;
		s_ComState[1] = 0u;
		s_ComState[2] = 0u;
		s_ComState[3] = 0u;
		MSCP_LOG_MSG("PFM_HardWareBoot_CheckSelf 1\n");
	}
	else
	{
		/*- 根据执行步骤进行继电器自检 */
		switch (s_selfcheck_state)
		{
			/*- 判断第一个继电器是否需要检测 */
			case ENUM_RELAY_1ST_OUTPUT:
				/*- 判断所有对系板卡通信状态并且记录*/
				s_ComState[0] = PFM_HardWareBoot_CheckSelf_ComState(ENUM_TYPE_PUB,s_ComState[0]);
				s_ComState[1] = PFM_HardWareBoot_CheckSelf_ComState(ENUM_TYPE_CCU,s_ComState[1]);
				s_ComState[2] = PFM_HardWareBoot_CheckSelf_ComState(ENUM_TYPE_SEB,s_ComState[2]);
				s_ComState[3] = PFM_HardWareBoot_CheckSelf_ComState(ENUM_TYPE_ESB,s_ComState[3]);
				/*- 如果第一个继电器需要自检 */
				if((1u == ((level>>3)&0x01)))
				{
					/*- 单步输出 */
					(void)DFM_SetIO_OutPut(0x08u);
					/*- 记录输出时刻周期 */
					s_OutPutTime = DFM_GetBirthCount();
					/*- 记录等待时间*/
					s_WaitTime = WAIT_TIME_2S;
					/*- 跳转第1继电器检测*/
					s_selfcheck_state = ENUM_RELAY_1ST_SELFCHECK;
					MSCP_LOG_MSG("PFM_HardWareBoot_CheckSelf 2\n");
				}
				else
				{
					/*- 跳过检测-跳转第2继电器输出 */
					MSCP_LOG_MSG("PFM_HardWareBoot_CheckSelf 3\n");
					s_selfcheck_state = ENUM_RELAY_2ND_OUTPUT;
				}
				/*- 跳出 */
				break;
			/*- 第1个继电器检测 */
			case ENUM_RELAY_1ST_SELFCHECK:
				/*- @alias 通过与各板卡通信判断继电器故障(主机重启继电器2故障，CCU重启继电器3故障，交换机重启继电器4故障) */
				(1 == PFM_HardWareBoot_CheckSelf_ComState(ENUM_TYPE_PUB,s_ComState[0])) ? (s_relay_default[1] = 0xAA) : (s_relay_default[1] = 0x55);
				(1 == PFM_HardWareBoot_CheckSelf_ComState(ENUM_TYPE_CCU,s_ComState[1])) ? (s_relay_default[2] = 0xAA) : (s_relay_default[2] = 0x55);
				(1 == PFM_HardWareBoot_CheckSelf_ComState(ENUM_TYPE_ESB,s_ComState[3])) ? (s_relay_default[3] = 0xAA) : (s_relay_default[3] = 0x55);
				comResult = s_relay_default[1] | s_relay_default[2] | s_relay_default[3];
				/*- 继电器检测 */
				s_selfcheck_state = PFM_Realy_Check(s_selfcheck_state, s_OutPutTime, comResult);
				MSCP_LOG_MSG("PFM_HardWareBoot_CheckSelf 4\n");
				/*- 跳出 */
				break;
				/*- 判断第二个继电器是否需要检测 */
			case ENUM_RELAY_2ND_OUTPUT:
				/*- 如果第二个继电器需要自检 */
				if(1u == ((level>>2)&0x01))
				{
					/*- 单步输出 */
					(void)DFM_SetIO_OutPut(0x04u);
					/*- 记录输出时刻 */
					s_OutPutTime = DFM_GetBirthCount();
					/*- 记录等待时间 */
					s_WaitTime = WAIT_TIME_2S;
					/*- 跳转第2继电器检测 */
					s_selfcheck_state = ENUM_RELAY_2ND_SELFCHECK;
					MSCP_LOG_MSG("PFM_HardWareBoot_CheckSelf 5\n");
				}
				else
				{
					/*- 跳过检测-跳转第3继电器输出 */
					s_selfcheck_state = ENUM_RELAY_3RD_OUTPUT;
					MSCP_LOG_MSG("PFM_HardWareBoot_CheckSelf 6\n");
				}
				/*- 跳出 */
				break;
				/*- 第2个继电器检测 */
			case ENUM_RELAY_2ND_SELFCHECK:
				/*- @alias 通过与各板卡通信判断继电器故障(主机重启继电器1故障，SEB重启继电器3故障) */
				(1 == PFM_HardWareBoot_CheckSelf_ComState(ENUM_TYPE_PUB,s_ComState[0])) ? (s_relay_default[0] = 0xAA) : (s_relay_default[0] = 0x55);
				(1 == PFM_HardWareBoot_CheckSelf_ComState(ENUM_TYPE_SEB,s_ComState[2])) ? (s_relay_default[2] = 0xAA) : (s_relay_default[2] = 0x55);
				comResult = s_relay_default[0] | s_relay_default[2];
				/*- 继电器检测 */
				s_selfcheck_state = PFM_Realy_Check(s_selfcheck_state, s_OutPutTime, comResult);
				MSCP_LOG_MSG("PFM_HardWareBoot_CheckSelf 7\n");
				/*- 跳出 */
				break;
				/*- 判断第三个继电器是否需要检测 */
			case ENUM_RELAY_3RD_OUTPUT:
				/*- 如果第三个继电器需要自检 */
				if(1u == ((level>>1)&0x01))
				{
					/*- 单步输出 */
					DFM_SetIO_OutPut(0x02u);
					/*- 记录输出时刻s */
					s_OutPutTime = DFM_GetBirthCount();
					/*- 记录等待时间s */
					s_WaitTime = WAIT_TIME_2S;
					/*- 跳转第3继电器检测 */
					s_selfcheck_state = ENUM_RELAY_3RD_SELFCHECK;
					MSCP_LOG_MSG("PFM_HardWareBoot_CheckSelf 8\n");
				}
				else
				{
					/*- 跳过检测-跳转第3继电器输出 */
					s_selfcheck_state = ENUM_RELAY_4TH_OUTPUT;
					MSCP_LOG_MSG("PFM_HardWareBoot_CheckSelf 9\n");
				}
				/*- 跳出 */
				break;
				/*- 第3个继电器检测 */
			case ENUM_RELAY_3RD_SELFCHECK:
				/*- @alias 通过与各板卡通信判断继电器故障(CCU重启继电器1故障，SEB重启继电器2故障) */
				(1 == PFM_HardWareBoot_CheckSelf_ComState(ENUM_TYPE_CCU,s_ComState[1])) ? (s_relay_default[0] = 0xAA) : (s_relay_default[0] = 0x55);
				(1 == PFM_HardWareBoot_CheckSelf_ComState(ENUM_TYPE_SEB,s_ComState[2])) ? (s_relay_default[1] = 0xAA) : (s_relay_default[1] = 0x55);
				comResult = s_relay_default[0] | s_relay_default[1];
				/*- 继电器检测 */
				s_selfcheck_state = PFM_Realy_Check(s_selfcheck_state, s_OutPutTime, comResult);
				MSCP_LOG_MSG("PFM_HardWareBoot_CheckSelf 10\n");
				/*- 跳出 */
				break;
				/*- 判断第四个继电器是否需要检测 */
			case ENUM_RELAY_4TH_OUTPUT:
				/*- 如果第四个继电器需要自检 */
				if(1u == (level&0x01))
				{
					/*- 单步输出 */
					(void)DFM_SetIO_OutPut(0x01u);
					/*- 记录输出时刻s */
					s_OutPutTime = DFM_GetBirthCount();
					/*- 记录等待时间s */
					s_WaitTime = WAIT_TIME_2S;
					/*- 跳转第4继电器检测 */
					s_selfcheck_state = ENUM_RELAY_4TH_SELFCHECK;
					MSCP_LOG_MSG("PFM_HardWareBoot_CheckSelf 11\n");
				}
				else
				{
					/*- 跳过检测-跳转全部继电器输出 */
					s_selfcheck_state = ENUM_RELAY_ALL_OUTPUT;
					MSCP_LOG_MSG("PFM_HardWareBoot_CheckSelf 12\n");
				}
				/*- 跳出 */
				break;
				/*- 第4个继电器检测 */
			case ENUM_RELAY_4TH_SELFCHECK:
				/*- 检测通信状态与2S检测时间，通信中断延长至10s */
				/*- 交换机重启-继电器1故障，EEB重启继电器2故障（无此板卡）*/
				(1 == PFM_HardWareBoot_CheckSelf_ComState(ENUM_TYPE_ESB,s_ComState[3])) ? (s_relay_default[0] = 0xAA) : (s_relay_default[0] = 0x55);
				comResult = s_relay_default[0];
				/*- 继电器检测 */
				s_selfcheck_state = PFM_Realy_Check(s_selfcheck_state, s_OutPutTime, comResult);
				MSCP_LOG_MSG("PFM_HardWareBoot_CheckSelf 13\n");
				/*- 跳出 */
				break;
				/*- 执行硬重启 */
			case ENUM_RELAY_ALL_OUTPUT:
				(void)DFM_SetIO_OutPut(level);
				/*- 记录输出时刻s */
				s_OutPutTime = DFM_GetBirthCount();
				/*- 记录等待时间2s */
				s_WaitTime = WAIT_TIME_2S;
				/*- 跳转硬重启检测 */
				s_selfcheck_state = ENUM_RELAY_BOOT_CHECK;
				MSCP_LOG_MSG("PFM_HardWareBoot_CheckSelf 14\n");
				/*- 跳出 */
				break;
				/*- 检测硬重启结果,等待电源断开 */
			case ENUM_RELAY_BOOT_CHECK:
				/*- 断电后没有通信 */
				comResult = PFM_HardWareBoot_CheckSelf_Com(board_type);
				/*- 通信正常 */
				if((DFM_GetBirthCount()-s_OutPutTime) < s_WaitTime)
				{
					if(WAIT_TIME_2S == s_WaitTime)
					{
						/* continue */
						MSCP_LOG_MSG("PFM_HardWareBoot_CheckSelf 15\n");
					}
					else
					{
						if(1u == comResult)
						{
							/*- 断开电源成功 */
							s_boot_result = 0x55u;
							/*- 等待2min电源启动 */
							s_WaitTime = WAIT_TIME_120S;
							s_selfcheck_state = ENUM_RELAY_BOOT_RESTART;
							(void)DFM_SetIO_OutPut(0x00u);
							MSCP_LOG_MSG("PFM_HardWareBoot_CheckSelf 16\n");
						}
						else
						{
							/* continue */
							MSCP_LOG_MSG("PFM_HardWareBoot_CheckSelf 17\n");
						}
					}
				}
				else
				{
					if(WAIT_TIME_2S == s_WaitTime)
					{
						s_WaitTime = WAIT_TIME_10S;
						MSCP_LOG_MSG("PFM_Realy_Check 18\n");
					}
					else
					{
						/*- 出现故障终止检测 */
						(1u == ((level>>3)&0x01)) ? (s_relay_default[0] = 0xAA) : (s_relay_default[0] = 0x55);
						(1u == ((level>>2)&0x01)) ? (s_relay_default[1] = 0xAA) : (s_relay_default[1] = 0x55);
						(1u == ((level>>1)&0x01)) ? (s_relay_default[2] = 0xAA) : (s_relay_default[2] = 0x55);
						(1u == (level&0x01)) ? (s_relay_default[3] = 0xAA) : (s_relay_default[3] = 0x55);
						s_boot_result = 0xAAu;
						s_selfcheck_state = ENUM_OUTPUT_RESULT;
						(void)DFM_SetIO_OutPut(0x00u);
						MSCP_LOG_MSG("PFM_HardWareBoot_CheckSelf 19\n");
					}
				}

				/*- 跳出 */
				break;
				/*- 等待启动结果 */
			case ENUM_RELAY_BOOT_RESTART:
				/*- 如果小于等待时间 */
				if((DFM_GetBirthCount()-s_OutPutTime) < s_WaitTime)
				{
					/*- 通信正常 */
					if(0u == PFM_HardWareBoot_CheckSelf_Com(board_type))
					{
						/*- 发送重启结果组包数据 */
						s_boot_result = 0x55u;
						s_selfcheck_state = ENUM_OUTPUT_RESULT;
					}
					else
					{
						/*- 无处理 */
					}
					MSCP_LOG_MSG("PFM_HardWareBoot_CheckSelf 22\n");
				}
				else
				{
					/*- 没有恢复通信失败 */
					s_boot_result = 0xAAu;
					s_selfcheck_state = ENUM_OUTPUT_RESULT;
					MSCP_LOG_MSG("PFM_HardWareBoot_CheckSelf 23\n");
				}
				/*- 跳出 */
				break;
				/*- 反馈执行结果 */
			case ENUM_OUTPUT_RESULT:
				/*- 发送结果至AID */
				MSCP_LOG_MSG("s_relay_default[0] = %d,s_relay_default[1] = %d,s_relay_default[2] = %d,s_relay_default[3] = %d\n",s_relay_default[0],s_relay_default[1],s_relay_default[2],s_relay_default[3]);
				PFM_HardWareBoot_CheckSelf_Response(s_boot_result,s_relay_default,reboottype);
				/*- 清空所有标志位 */
				s_selfcheck_state = ENUM_RELAY_1ST_OUTPUT;
				s_OutPutTime = 0u;
				s_WaitTime = 0u;
				s_boot_result = 0xAAu;
				s_relay_default[0] = 0x55u;
				s_relay_default[1] = 0x55u;
				s_relay_default[2] = 0x55u;
				s_relay_default[3] = 0x55u;
				s_ComState[0] = 0u;
				s_ComState[1] = 0u;
				s_ComState[2] = 0u;
				s_ComState[3] = 0u;
				MSCP_LOG_MSG("PFM_HardWareBoot_CheckSelf 24\n");
				break;
				/*- 无 */
			default:
				/*- 跳出 */
				break;
		}
	}
	MSCP_LOG_MSG("PFM_HardWareBoot_CheckSelf 25\n");
	/*- 返回执行步骤 */
	return s_selfcheck_state;
}

/**
* @brief 识别AB系通信需要计算的板卡通信状态(对系)
* @param type 当前判断板卡通信状态类型 取值范围：取值范围：1~5
* @return 0是通信正常，1是通信中断
*/
CM_UINT8 PFM_HardWareBoot_CheckSelf_Com(ENUM_BOARD_TYPE_T type)
{
	/*- 变量初始化 */
	CM_UINT8 ret = 1u;/* 返回值 */
	CM_UINT8 RetState[4] = {0u,0u,0u,0u};/* 继电器故障记录 */
	/*- 判断板卡类型 */
	switch (type)
	{
	/*- 如果是主机板 */
	case ENUM_TYPE_PUB:
		/*- 判断邻机主机是否通信中断 */
		ret = SFM_2x2_GetWithPeer_Com_State();
		/*- 跳出 */
		break;
	/*- 如果是通控板 */
	case ENUM_TYPE_CCU:
		/*- @alias 判断对系通控是否通信中断 */
		if(1u == g_RMUP_Cfg.BOARD_ID)
		{
			ret = ((g_Hardware_boot_com_state.SYS_Count - g_Hardware_boot_com_state.CCU_B_Count) > 0)?1u:0u;
		}
		else
		{
			ret = ((g_Hardware_boot_com_state.SYS_Count - g_Hardware_boot_com_state.CCU_A_Count) > 0)?1u:0u;
		}
		/*- 跳出 */
		break;
	/*- 如果是串口板 */
	case ENUM_TYPE_SEB:
		/*- @alias 判断对系串口板是否通信中断 */
		if(1u == g_RMUP_Cfg.BOARD_ID)
		{
			ret = ((g_Hardware_boot_com_state.SYS_Count - g_Hardware_boot_com_state.SEB_B_Count) > 0)?1u:0u;
		}
		else
		{
			ret = ((g_Hardware_boot_com_state.SYS_Count - g_Hardware_boot_com_state.SEB_A_Count) > 0)?1u:0u;
		}
		/*- 跳出 */
		break;
	/*- 如果是交换机板 */
	case ENUM_TYPE_ESB:
		/*- @alias 间接判断对系交换机是否通信中断 */
		if(1u == g_RMUP_Cfg.BOARD_ID)
		{
			/*- A系判断紫网B系交换机 */
			if(1u == g_RMUP_Cfg.CPU_ID)
    		{
				ret =  SFM_2x2_GetWithESB_Peer_Com_State();
    		}
    		else
    		{
				ret =  SFM_2x2_GetWithESB_Mine_Com_State();
    		}
		}
		else
		{
			if(1u == g_RMUP_Cfg.CPU_ID)
    		{
				ret =  SFM_2x2_GetWithESB_Mine_Com_State();
    		}
    		else
    		{
				ret =  SFM_2x2_GetWithESB_Peer_Com_State();
    		}
		}
		/*- 跳出 */
		break;
	/*- 如果是所有板卡 */
	case ENUM_TYPE_ALL:
		/*- @alias 判断所有板卡通信状态*/
		RetState[0] = PFM_HardWareBoot_CheckSelf_Com(ENUM_TYPE_PUB);
		RetState[1] = PFM_HardWareBoot_CheckSelf_Com(ENUM_TYPE_CCU);
		(NULL != p_Serial_Id_Func) ? (RetState[2] = PFM_HardWareBoot_CheckSelf_Com(ENUM_TYPE_SEB)) : (RetState[2] = 0);
		RetState[3] = PFM_HardWareBoot_CheckSelf_Com(ENUM_TYPE_ESB);
		MSCP_LOG_MSG("ENUM_TYPE_PUB = %d,ENUM_TYPE_CCU = %d,ENUM_TYPE_SEB = %d,ENUM_TYPE_ESB = %d\n"\
				,RetState[0],RetState[1],RetState[2],RetState[3]);
		if(RetState[0] || RetState[1] || RetState[2] || RetState[3])
		{
			ret = 1u;
		}
		else
		{
			ret = 0u;
		}
		/*- 跳出 */

		break;
	default:
		ret = 1u;
		/*- 跳出 */
		break;
	}

	/*- 返回检测结果 */
	return ret;
}

/**
* @brief 识别AB系通信需要计算的板卡通信状态(对系)
* @param type 当前判断板卡通信状态类型 取值范围：1~5
* @param s_ComState 0代表初始有通信,1代表初始没通信
* @return 0是通信正常，1是通信中断
*/
CM_UINT8 PFM_HardWareBoot_CheckSelf_ComState(ENUM_BOARD_TYPE_T type, CM_UINT8 s_ComState)
{
	/*- 变量初始化 */
	CM_UINT8 ret = 1u;
	/*- 如果初始有通信 */
	if(0 == s_ComState)
	{
		/*- 检测通信是否异常*/
		ret = PFM_HardWareBoot_CheckSelf_Com(type);
	}
	else
	{
		/*- 不检测 */
		ret = 0;
	}

	/*- 返回通信结果 */
	return ret;
}
/**
* @brief 组包发送硬重启自检执行结果
* @param boot_result 硬重启结果 取值范围：0x55成功，0xAA失败
* @param *defaultbuf 继电器检测结果数组 取值范围：0x55成功，0xAA故障
* @param reboottype  重启命令类型 取值范围：0xd1~0xd7
* @return 无
*/
void PFM_HardWareBoot_CheckSelf_Response(CM_UINT8 boot_result,CM_UINT8 *defaultbuf,CM_UINT8 reboottype)
{
	/*- 变量初始化 */
	CM_UINT8 mData[1000] = { 0u };
	CM_UINT32 dataOffset = 2u;/*- 长度预留 */
	CM_UINT16 packLen = 0u;
	CM_UINT32 calcCrc1 = 0u;
	CM_UINT32 calcCrc2 = 0u;
	CM_UINT8 ret = 0u;
	/*- 入参指针是否不为空 */
	if(NULL != defaultbuf)
	{
		/*- @alias 组硬重启自检执行结果数据帧 */
		/* 帧类型 */
		mData[dataOffset++] = 0x59u;
		/*- 板卡类型主机板1 */
		mData[dataOffset++] = 1u;
		/* 通道ID */
		if(1u == g_RMUP_Cfg.BOARD_ID)
		{
			mData[dataOffset++] = 0xA0u;
		}
		else
		{
			mData[dataOffset++] = 0x0Bu;
		}
		/* 重启命令类型 */
		mData[dataOffset++] = reboottype;
		/* 重启结果 */
		mData[dataOffset++] = boot_result;
		/* 继电器检测状态 */
		mData[dataOffset++] = defaultbuf[0u];
		mData[dataOffset++] = defaultbuf[1u];
		mData[dataOffset++] = defaultbuf[2u];
		mData[dataOffset++] = defaultbuf[3u];
		/* 计算CRC*/
		calcCrc1 = CM_Crc32(&mData[3], dataOffset - 3u);
		CM_LongToChar(calcCrc1, &mData[dataOffset]);
		dataOffset += 4u;

		calcCrc2 = CM_Crc32(&mData[2], dataOffset - 2u);
		CM_LongToChar(calcCrc2, &mData[dataOffset]);
		dataOffset += 4u;
		packLen = dataOffset - 2u;
		CM_ShortToChar(packLen, &mData[0]);
		ret = Prtcl_InnetSafe_AppRmSend(mData,dataOffset);
		if(ret == 0)
		{
			/*- 输出异常警告 */
			MSCP_LOG_MSG("checkself_response 0x59 ERR!!!\n");
		}
	}
	else
	{
		/*- 类型错误无处理*/
		(void)CFM_DarkLog_Storage(DARK_LOG_HEX, TSCP_DARK_WARNING, 4U, DARK_FAULT_CODE_MERGE(REMOTE_UPDATE, DARK_FAULT_CODE_FUN_ORDER_17, TSCP_DARK_ASSERT_1));
	}
}


/**
* @brief 识别AB系通信需要计算的板卡通信状态
* @param type 当前判断板卡通信状态类型 取值范围：0~3 0红通控 1蓝通控 2红串口 3蓝串口
* @return 0是通信正常，1是通信中断
*/
CM_UINT8 PFM_CCUSEB_Comstate(CM_UINT8 type)
{
	CM_UINT8 ret = 1u;/*- 返回值 */
	switch (type)
	{
	case 0:
		/*- 判断红通控是否通信中断 */
		ret = ((g_Hardware_boot_com_state.SYS_Count - g_Hardware_boot_com_state.CCU_A_Count) > 1)?1u:0u;
		break;
	case 1:
		/*- 判断蓝通控是否通信中断 */
		ret = ((g_Hardware_boot_com_state.SYS_Count - g_Hardware_boot_com_state.CCU_B_Count) > 1)?1u:0u;
		break;
	case 2:
		/*- 判断红串口是否通信中断 */
		ret = ((g_Hardware_boot_com_state.SYS_Count - g_Hardware_boot_com_state.SEB_A_Count) > 1)?1u:0u;
		break;
	case 3:
		/*- 判断蓝串口是否通信中断 */
		ret = ((g_Hardware_boot_com_state.SYS_Count - g_Hardware_boot_com_state.SEB_B_Count) > 1)?1u:0u;
		break;
	default:
		ret = 1u;
		break;
	}

	return ret;
}

/**
* @brief 继电器检测
* @param s_selfcheck_state 当前检测步骤 取值范围：0~11
* @param s_OutPutTime 检测的开始时间 取值范围：0~0xffffffff
* @param comResult 板卡通信状况 取值范围：0x55,0xaa
* @return ENUM_HARDWARE_BOOT_SELFCHECK_T 当前检测步骤 取值范围：0~11
*/
static ENUM_HARDWARE_BOOT_SELFCHECK_T PFM_Realy_Check(ENUM_HARDWARE_BOOT_SELFCHECK_T s_selfcheck_state,CM_UINT32 s_OutPutTime, CM_UINT8 comResult)
{
	/*- 变量初始化 */
	CM_UINT32 birthCyc = DFM_GetBirthCount();
	/*- 通信正常 */
	if((birthCyc-s_OutPutTime) < s_WaitTime)
	{
		if(WAIT_TIME_2S == s_WaitTime)
		{
			/* continue */
			MSCP_LOG_MSG("PFM_Realy_Check 1\n");
		}
		else
		{
			if(0x55u == comResult)
			{
				/*- 继续检测下一个继电器 */
				(void)DFM_SetIO_OutPut(0x00u);
				s_selfcheck_state++;
				MSCP_LOG_MSG("PFM_Realy_Check 2\n");
			}
			else
			{
				/* continue */
				MSCP_LOG_MSG("PFM_Realy_Check 3\n");
			}
		}
	}
	else
	{
		if(WAIT_TIME_2S == s_WaitTime)
		{
			s_WaitTime = WAIT_TIME_10S;
			MSCP_LOG_MSG("PFM_Realy_Check 4\n");
		}
		else
		{
			/*- 出现故障终止检测 */
			(void)DFM_SetIO_OutPut(0x00u);
			s_selfcheck_state = ENUM_OUTPUT_RESULT;
			MSCP_LOG_MSG("PFM_Realy_Check 5\n");
		}
	}

	return s_selfcheck_state;
}
