| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965 | /** Brief:	Receive message from Interface and send response to original interface.			Process all IPMI standard command and oem command.* Author:	Jimbo_Zhang@outlook.com* Date:		2019-9-13, the Mid-autumn Festival;*/#include <stdio.h>#include <sys/stat.h>#include <sys/socket.h>#include <sys/un.h>#include <sys/prctl.h>#include <errno.h>#include <fcntl.h>#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include <pthread.h>#include "MsgHndlr.h"#include "PDKCmds.h"#include "App.h"#include "PICMG.h"#include "Bridge.h"#include "SensorEvent.h"#include "Chassis.h"#include "Storage.h"#include "cmdselect.h"#include "com_IPMI_App.h"#include "com_IPMI_Storage.h"#include "com_IPMI_SDR.h"#include "DeviceConfig.h"//#include "main.h"#include <string.h>#include "main.h"static void ProcessIPMIReq (MsgPkt_T* pReq, MsgPkt_T* pRes);static void PendingBridgeResTimerTask (void);static void PendingSeqNoTimerTask (void);MsgHndlrTbl_T m_MsgHndlrTbl [] =	//notice!{	{ NETFN_APP,                    g_App_CmdHndlr                  },	{ NETFN_CHASSIS,                g_Chassis_CmdHndlr              },	{ NETFN_BRIDGE,                 g_Bridge_CmdHndlr               },	{ NETFN_SENSOR,                 g_SensorEvent_CmdHndlr          },	{ NETFN_STORAGE,                g_Storage_CmdHndlr              },	{ NETFN_TRANSPORT,              g_Config_CmdHndlr               },//	{ NETFN_AMI,                    (CmdHndlrMap_T*)g_AMI_CmdHndlr  },	{	0,							0	},};GroupExtnMsgHndlrTbl_T m_GroupExtnMsgHndlrTbl [] =		//jimbo add{	{0,		0},};TimerTaskTbl_T    m_TimerTaskTbl [20] ={//	{ 1,    PEFTimerTask	},//	{ 1,    PETAckTimerTask },//	{ 1,    PEFStartDlyTimerTask },	{ 1,    SessionTimerTask },//	{ 1,    PendingBridgeResTimerTask },//	{ 1,    PendingSeqNoTimerTask },//	{ 1,    FlashTimerTask },//	#if FRB_SUPPORT == 1//	{ 1,    FRB3TimerTask   },//	#endif /* #if FRB_SUPPORT == 1 */////	#if SERIAL_MODEM_CONNECTION_ACTIVITY  != UNIMPLEMENTED//	{ 2,    SerialModemPingTask },//	#endif /* SERIAL_MODEM_CONNECTION_ACTIVITY */////	{ 1,    MonitorPassword },	{ 1,    UDSSessionTimerTask },};//PendingBridgedResTbl_T	m_PendingBridgedResTbl[MAX_PENDING_BRIDGE_RES];PendingBridgedResTbl_T	m_PendingBridgedResTbl[MAX_PENDING_BRIDGE_TBL][MAX_PENDING_BRIDGE_RES];PendingSeqNoTbl_T	m_PendingSeqNoTbl[16][MAX_PENDING_SEQ_NO];KCSBridgeResInfo_T       m_KCSBridgeResInfo;int gFd_MsgHndlrIfc;TLS_T g_tls;/*!    \brief      Message handler Task. Process all standard and oem ipmi message form interface, and send response back.    \param[in]  none    \param[out] none    \retval     none*/void *MsgHndlrTask( void *pArg ){	MsgPkt_T reqMsgPkt;	MsgPkt_T resMsgPkt;	uint8_t channelinit = 0xF;	printf("MsgHndlrTask start...\r\n");	prctl(PR_SET_NAME,__FUNCTION__,0,0,0); 	//create     if(-1 != access(MSG_HNDLR_Q, F_OK))    {        remove(MSG_HNDLR_Q);    }    if(0 != mkfifo (MSG_HNDLR_Q, 0777))    {        printf("%s: Create %s fifo failed! %s\n", __FUNCTION__, MSG_HNDLR_Q, strerror(errno));        return (void*)-1;    }    gFd_MsgHndlrIfc = open (MSG_HNDLR_Q, O_RDWR);    if(-1 == gFd_MsgHndlrIfc)    {        printf("%s: Open %s fifo failed! %s\n", __FUNCTION__, MSG_HNDLR_Q, strerror(errno));        return (void*)-1;    }		pthread_key_create(&g_tls.CurSessionID,NULL);	pthread_key_create(&g_tls.CurPrivLevel,NULL);	pthread_key_create(&g_tls.CurChannel,NULL);	pthread_key_create(&g_tls.CurKCSIfcNum,NULL);	pthread_key_create(&g_tls.CurSessionType,NULL);	pthread_key_create(&g_tls.OwnerLUN,NULL);	pthread_setspecific(g_tls.CurChannel,&channelinit);	while(1)	{		while(GetMsg(gFd_MsgHndlrIfc, &reqMsgPkt, WAIT_INFINITE) != 0);		// printf("===> Mrx: ");		// int i;		// for(i=0;i<reqMsgPkt.Size;i++)		// 	printf("%#x ", reqMsgPkt.Data[i]);		// printf("\n");		pthread_setspecific(g_tls.CurChannel,&reqMsgPkt.Channel);		pthread_setspecific(g_tls.CurPrivLevel,&reqMsgPkt.Privilege);		pthread_setspecific(g_tls.CurSessionID,&reqMsgPkt.SessionID);		pthread_setspecific(g_tls.CurSessionType,&reqMsgPkt.SessionType);		pthread_setspecific(g_tls.OwnerLUN,&reqMsgPkt.NetFnLUN);		SwapIPMIMsgHdr ((IPMIMsgHdr_T*)reqMsgPkt.Data, (IPMIMsgHdr_T*)resMsgPkt.Data);		ProcessIPMIReq(&reqMsgPkt, &resMsgPkt);		/* Skip current request if no response from Command Handler */		if ((reqMsgPkt.SrcQ == gFd_LanResQ) && (sizeof(IPMIMsgHdr_T) == resMsgPkt.Size) && (NORMAL_RESPONSE == resMsgPkt.Param) )		{			continue;		}		if ((reqMsgPkt.SrcQ == gFdUdsRes) && (resMsgPkt.Size == sizeof(IPMIUDSMsg_T)) && (NORMAL_RESPONSE == resMsgPkt.Param) )		{			continue;		}		//update checksum2		resMsgPkt.Data[resMsgPkt.Size]	=	CalculateCheckSum2(resMsgPkt.Data, resMsgPkt.Size);		resMsgPkt.Size++;		if(g_BMCInfo.IpmiConfig.UDSIfcSupport == 0x01 && (reqMsgPkt.SrcQ == gFdUdsRes))		{						resMsgPkt.Size = resMsgPkt.Size+1;			SwapUDSIPMIMsg(&reqMsgPkt,&resMsgPkt);			resMsgPkt.Data[resMsgPkt.Size-1] = 0;		}		if(SYS_IFC_CHANNEL == reqMsgPkt.Channel)		{  			/* Skip current request if no response from Command Handler */			if (!resMsgPkt.Size && (NO_RESPONSE == resMsgPkt.Param) )			{				continue;			}						resMsgPkt.SessionID = reqMsgPkt.SessionID;		}		//int i;		// printf("===> Mtx to %d: ", resMsgPkt.SrcQ);		// for(i=0;i<resMsgPkt.Size;i++)		// 	printf("%#x ", resMsgPkt.Data[i]);		// printf("\n");		//send response pkt to source queue.		PostMsg(resMsgPkt.SrcQ, &resMsgPkt);			}}/***@fn ValidateMsgHdr*@brief Validates the Message header and keeps track of the messages that has been bridged*@param pReq Request packet of the command to be executed*@return Returns -1 in case of the response to the bridged message*            Returns 0 otherwise*/intValidateMsgHdr (MsgPkt_T* pReq){	int  j;	uint8_t PBTbl = PRIMARY_PB_TBL;	IPMIMsgHdr_T*	pIPMIMsgReq = (IPMIMsgHdr_T*)&pReq->Data;	ChannelInfo_T*  pChannelInfo;	uint8_t SeqNum = NET_FN(pIPMIMsgReq->RqSeqLUN);	int Queuefd = 0;	/* Check for the request message LUN */	switch (pReq->NetFnLUN & 0x03)	{		case BMC_LUN_00:			if (0 == (pReq->NetFnLUN & 0x04))			{				return 0;	//IPMB做从			}			PBTbl = ( (pReq->Channel == SECONDARY_IPMB_CHANNEL) ? SECONDARY_PB_TBL : PRIMARY_PB_TBL );									if ( (TRUE 		== m_PendingBridgedResTbl[PBTbl][SeqNum].Used) &&				 (NET_FN(pIPMIMsgReq->NetFnLUN)  == NET_FN((m_PendingBridgedResTbl[PBTbl][SeqNum].ReqMsgHdr.NetFnLUN + 0x04)))  &&				 (pIPMIMsgReq->Cmd               == m_PendingBridgedResTbl[PBTbl][SeqNum].ReqMsgHdr.Cmd)  &&				 (pIPMIMsgReq->ReqAddr           == m_PendingBridgedResTbl[PBTbl][SeqNum].ReqMsgHdr.ResAddr))			{        				 /* Change the requester's address, sequence number and LUN */				 pIPMIMsgReq->ResAddr  = m_PendingBridgedResTbl[PBTbl][SeqNum].ReqMsgHdr.ReqAddr;				 pIPMIMsgReq->RqSeqLUN = m_PendingBridgedResTbl[PBTbl][SeqNum].ReqMsgHdr.RqSeqLUN;				 /* Calculate the Second CheckSum */				 pReq->Data[ pReq->Size - 1 ] = CalculateCheckSum2( pReq->Data, pReq->Size - 1 );				 pReq->Data[2] = (~(pReq->Data[0] + pReq->Data[1])) +1; //2's complement checksum				 pReq->Param = BRIDGING_REQUEST;				 				 if (m_PendingBridgedResTbl[PBTbl][SeqNum].DestQ == gFd_LanIfcQ)				 {								  for (j=pReq->Size - 1; j>=0; j--)					  {						   pReq->Data[j+1] = pReq->Data[j];					  }					  pReq->Data[0] = m_PendingBridgedResTbl[PBTbl][SeqNum].SrcSessionHandle;					  pReq->Size++;					  pReq->Cmd = PAYLOAD_IPMI_MSG;					  Queuefd = gFd_LanIfcQ;				 }				 else if(m_PendingBridgedResTbl[PBTbl][SeqNum].DestQ == gFdUdsIfc)				 {				 	pReq->Cmd = PAYLOAD_IPMI_MSG;				 	pReq->Socket = m_PendingBridgedResTbl[PBTbl][SeqNum].UDSSocket;				 	memcpy(&pReq->Data[sizeof(IPMIUDSMsg_T)], &pReq->Data[0], pReq->Size);				 	memcpy(&pReq->Data[0], &m_PendingBridgedResTbl[PBTbl][SeqNum].ResMsgHdr.UDSMsgHdr, sizeof(IPMIUDSMsg_T));				 	pReq->Size += sizeof(IPMIUDSMsg_T);				 	pReq->Size++;				 	pReq->Data[pReq->Size-1] = 0;				 	((IPMIUDSMsg_T*)&pReq->Data[0])->IPMIMsgLen = pReq->Size;				 	Queuefd = gFdUdsIfc;				 }				 else				 {				 	Queuefd = m_PendingBridgedResTbl[PBTbl][SeqNum].DestQ;				 }										 /* Post the data to Destination Interface queue */				 printf("===> ValidateMsgHdr post message to %d\n", Queuefd);				 PostMsg (Queuefd, pReq);				 m_PendingBridgedResTbl[PBTbl][SeqNum].Used = FALSE;				 m_PendingBridgedResTbl[PBTbl][SeqNum].ResDataOk = 0;			}			return -1;		case BMC_LUN_01:		case BMC_LUN_10:		case BMC_LUN_11:			//TODO:		default:			return -1;	}}/***@fn ProcessIPMIReq*@brief Processes the requested IPMI command*@param pReq Request of the command*@param pRes Response for the requested command*@return none*/static voidProcessIPMIReq (MsgPkt_T* pReq, MsgPkt_T* pRes){	CmdHndlrMap_T *    	pCmdHndlrMap;	uint32_t            HdrOffset = 0;	uint8_t				CmdOverride = 1;	int8_t 				MsgHndlrMapGot=0;	uint8_t              PBTbl = PRIMARY_PB_TBL;	//	msgHndlr_dbg_printf ("Processing IPMI Packet.\r\n");	/* Set the Cmd and Net function in response packet */	pRes->Cmd		= 	pReq->Cmd;	pRes->NetFnLUN	= 	pReq->NetFnLUN;	pRes->Channel	=	pReq->Channel;	pRes->SrcQ		=	pReq->SrcQ;	pRes->Socket 	=	pReq->Socket;	/* Normal IPMI Command response */	pRes->Param 	= 	PARAM_NORMAL_RESPONSE;		if ((SYS_IFC_CHANNEL != pReq->Channel) && (USB_CHANNEL != pReq->Channel) && (UDS_CHANNEL != pReq->Channel))	{		//printf("log 1, pReq->Channel: %#x\n", pReq->Channel);		HdrOffset = sizeof (IPMIMsgHdr_T);		pReq->Size  = pReq->Size - HdrOffset - 1;	}	if(UDS_CHANNEL == pReq->Channel)	{		//printf("log 2, pReq->Size: %d, HdrOffset: %d\n", pReq->Size, HdrOffset);		HdrOffset = sizeof(IPMIUDSMsg_T);		pReq->Size = pReq->Size -HdrOffset - 1;	}		SwapIPMIMsgHdr((IPMIMsgHdr_T*)pReq->Data, (IPMIMsgHdr_T*)pRes->Data);	pRes->Size  = HdrOffset + sizeof(uint8_t);	pthread_setspecific(g_tls.CurSessionID,&pReq->SessionID);	if(IsCommandEnabled(NET_FN(pReq->NetFnLUN), &pReq->Data[HdrOffset], pReq->Cmd) != 0)	{		pRes->Data [HdrOffset] = CC_INV_CMD;		printf ("Invalid Net Function 0x%x or Invalid Command 0x%x\n",NET_FN(pReq->NetFnLUN), pReq->Cmd);		pRes->Size	+= 2;		return;	}		//Get oem command map	MsgHndlrMapGot = PDKGetOEMMsgHndlrMap(NET_FN(pReq->NetFnLUN),&pCmdHndlrMap);	if(MsgHndlrMapGot == 0)	{		CmdOverride = GetCmdHndlr(pReq,pRes,pCmdHndlrMap,HdrOffset,CmdOverride,&pCmdHndlrMap);	}		//get standard ipmi command map	if((CmdOverride == 0 || MsgHndlrMapGot == -1) )	//OEM commands have no command map.    {		if (0 != GetMsgHndlrMap (NET_FN (pReq->NetFnLUN), &pCmdHndlrMap))		{			// if(pBMCInfo->IpmiConfig.GrpExtnSupport == 1)			// {				if (0 != GroupExtnGetMsgHndlrMap (NET_FN (pReq->NetFnLUN), pReq->Data [HdrOffset], &pCmdHndlrMap) )				{					pRes->Data [HdrOffset] = CC_INV_CMD;					printf ("MsgHndlr.c : Invalid Net Function 0x%x or Invalid Command 0x%x\n",NET_FN(pReq->NetFnLUN), pReq->Cmd);					pRes->Size	+= 2;					return;				}			// }			// else			// {			// 	pRes->Data [HdrOffset] = CC_INV_CMD;			// 	printf ("MsgHndlr.c : Invalid Net Function 0x%x\n",NET_FN(pReq->NetFnLUN));			// 	pRes->Size	+= 2;			// 	return;			// }		}		if(GetCmdHndlr(pReq,pRes,pCmdHndlrMap,HdrOffset,CmdOverride,&pCmdHndlrMap) == FALSE)		{			pRes->Data [HdrOffset] = CC_INV_CMD;			pRes->Size	+= 2;			//printf("log 3\n");			return;		}   }   	/* Check for the request size */	if (0xff != pCmdHndlrMap->ReqLen)	{		/* Check for invalid request size */		if (pCmdHndlrMap->ReqLen != pReq->Size)		{				printf("Warning: Request data len error, require %d\n", pCmdHndlrMap->ReqLen);			pRes->Data [HdrOffset] = CC_REQ_INV_LEN;			pRes->Size	+= 2;			return;		}	}		pRes->Size 	= 	pCmdHndlrMap->CmdHndlr (&pReq->Data [HdrOffset], pReq->Size, &pRes->Data [HdrOffset]) + HdrOffset;			//prepare response data for send message command	if( (CMD_SEND_MSG == pReq->Cmd) && (NETFN_APP == pReq->NetFnLUN >> 2))	{		printf("log 4, size %d, Channel %d\n",pRes->Size, pRes->Channel);		int Offset = 0;		uint8_t SeqNum = g_BMCInfo.SendMsgSeqNum;		if ((0 == pRes->Size) &&			((g_BMCInfo.IpmiConfig.PrimaryIPMBSupport == 0x01  && PRIMARY_IPMB_CHANNEL == pRes->Channel) || 			 (g_BMCInfo.IpmiConfig.SecondaryIPMBSupport == 0x01 && SECONDARY_IPMB_CHANNEL == pRes->Channel)) )		{			pRes->Param = PARAM_NO_RESPONSE;			Offset = HdrOffset + 2;		}		else if (HdrOffset == pRes->Size)		{			Offset = HdrOffset + 1;		}	    PBTbl = ( ((pReq->Data[sizeof (IPMIMsgHdr_T)] & 0x0F) == SECONDARY_IPMB_CHANNEL) ? SECONDARY_PB_TBL : PRIMARY_PB_TBL );				int i;		while(TRUE)		{ 			if ( (TRUE == m_PendingBridgedResTbl[PBTbl][SeqNum].Used) 				&& (0 == memcmp (&m_PendingBridgedResTbl[PBTbl][SeqNum].ReqMsgHdr, &pReq->Data[Offset], sizeof (IPMIMsgHdr_T))) )			{				if(m_PendingBridgedResTbl[PBTbl][SeqNum].DestQ == gFd_LanIfcQ)				{									memcpy (&m_PendingBridgedResTbl[PBTbl][SeqNum].ResMsgHdr, pRes->Data, sizeof (IPMIMsgHdr_T));				}				else if(m_PendingBridgedResTbl[PBTbl][SeqNum].DestQ == gFdUdsIfc)				{					//pRes->Size ++;					SwapUDSIPMIMsg ( pReq, pRes);					//pRes->Data[pRes->Size-1] = 0;					memcpy (&m_PendingBridgedResTbl[PBTbl][SeqNum].ResMsgHdr, pRes->Data, sizeof (IPMIUDSMsg_T));						m_PendingBridgedResTbl[PBTbl][SeqNum].UDSSocket = pRes->Socket;					printf("log666 \n");					for(i=0;i<sizeof (IPMIUDSMsg_T);i++)						printf("%#x ", pRes->Data[i]);					printf("\n");				}				 m_PendingBridgedResTbl[PBTbl][SeqNum].ResDataOk = 1;				 break;    			}			else			{				SeqNum = (SeqNum - 1) & 0x3F;				if(SeqNum == g_BMCInfo.SendMsgSeqNum)				{					break; 				}			}		}	}		return;}/***@fn CalculateChecksum2*@brief Calculates the checksum*@param Pkt Pointer to the data for the checksum to be calculated*@param Len Size of data for checksum calculation*@return Returns the checksum value*/uint8_t CalculateCheckSum2 (uint8_t* Pkt, uint32_t Len){	uint8_t	Sum;	uint32_t	i;	/* Get Checksum 2 */	Sum = 0;	for (i = 3; i < Len; i++)	{		Sum += Pkt [i];	}	return (uint8_t)(0xFF & (0x100 - Sum));}/***@fn GetMsgHndlrMap*@brief Gets the exact command Handler by comparing NetFn*@param Netfn -NetFunction of the Cmd to execute*@param pCmdHndlrMap Pointer to the Command Handler*@return Returns 0 on success*            Returns -1 on failure*/intGetMsgHndlrMap (uint8_t NetFn, CmdHndlrMap_T ** pCmdHndlrMap){	int i;	/* Get the command handler corresponding to the net function */	for (i = 0; i <  sizeof(m_MsgHndlrTbl)/sizeof(m_MsgHndlrTbl[0]); i++)		//pBMCInfo->MsgHndlrTblSize 	{		if (m_MsgHndlrTbl [i].NetFn == NetFn) { break; }	}	/* Check if we have not found our net function */	if (i ==  sizeof(m_MsgHndlrTbl)/sizeof(m_MsgHndlrTbl[0]) )	{		return -1;	}	/* Get the handler corresponding to the command */	*pCmdHndlrMap = (CmdHndlrMap_T*)m_MsgHndlrTbl [i].CmdHndlrMap;	return 0;}/***@fn GetCmdHndlr*@brief Picks up the exact command to execute by comparing Cmd no.*@param pReq Request buffer for the command*@param pRes Response buffer for the command*@param pCmdHndlrMap*@param HdrOffset*@param CmdOverride*@param CmdHndlr*@return Returns TRUE on success*            Returns FALSE on failure*/int GetCmdHndlr(MsgPkt_T* pReq,MsgPkt_T* pRes,CmdHndlrMap_T* pCmdHndlrMap,								uint32_t HdrOffset,uint8_t CmdOverride,CmdHndlrMap_T** CmdHndrl ){	int i=0;	while (1)	{		/**		* If we reached the end of the Command Handler map - invalid command		**/		if (0 == pCmdHndlrMap->CmdHndlr)		{			if(CmdOverride == FALSE)			{				pRes->Data [HdrOffset] = CC_INV_CMD;				printf( "Warning: MsgHndlr.c : Invalid Command %#x\r\n", pReq->Cmd );			}			return FALSE;		}		if (pCmdHndlrMap->Cmd == pReq->Cmd)		{			break;		}				i++;		pCmdHndlrMap++;	}	*CmdHndrl = pCmdHndlrMap;	return TRUE;}/***@fn GroupExtnGetMsgHndlrMap*@brief Gets the exact command Handler by comparing NetFn*@param Netfn -NetFunction of the Cmd to execute*@GroupExtnCode - Group Extension code*@param pCmdHndlrMap Pointer to the Command Handler*@return Returns 0 on success*            Returns -1 on failure*/intGroupExtnGetMsgHndlrMap (uint8_t NetFn, uint8_t GroupExtnCode, CmdHndlrMap_T ** pCmdHndlrMap){	int i;	/* Get the command handler corresponding to the net function */	for (i = 0; i < sizeof (m_GroupExtnMsgHndlrTbl) / sizeof (m_GroupExtnMsgHndlrTbl [0]); i++)	{		if ((m_GroupExtnMsgHndlrTbl [i].NetFn == NetFn) && (m_GroupExtnMsgHndlrTbl [i].GroupExtnCode == GroupExtnCode)) 		{			break; 		}	}	/* Check if we have not found our net function */	if (i == sizeof (m_GroupExtnMsgHndlrTbl) / sizeof (m_GroupExtnMsgHndlrTbl[0]))	{		return -1;	}//	printf("---> GroupExtnGetMsgHndlrMap successful, i=%d\n",i);	/* Get the handler corresponding to the command */	*pCmdHndlrMap = (CmdHndlrMap_T*)m_GroupExtnMsgHndlrTbl [i].CmdHndlrMap;	return 0;}/*------------------------------------------------------------------ *@fn RespondSendMessage *@brief Frames the Response packet when a IPMB destination is *       unavialable * *@param pReq:    Request Message Packet address *@param Status   Status of SendIPMBPkt method *@param BMCInst: BMC Instance Number * *@return none *-----------------------------------------------------------------*/void RespondSendMessage ( MsgPkt_T* pReq, uint8_t Status){	uint8_t PBTbl = PRIMARY_PB_TBL;	MsgPkt_T   ResPkt;	IPMIMsgHdr_T*  pIPMIResHdr = ( IPMIMsgHdr_T*)ResPkt.Data;	IPMIMsgHdr_T*  pIPMIReqHdr = ( IPMIMsgHdr_T*)pReq->Data;	uint8_t SeqNum = NET_FN(pIPMIReqHdr->RqSeqLUN);		//IPMB的sequence	int QueueFd;	int HdrOffset = 0;		//printf("---> RespondSendMessage Status = %d, log111\n", Status);  /* Check for pending responses */	PBTbl = ( (pReq->Channel == SECONDARY_IPMB_CHANNEL) ? SECONDARY_PB_TBL : PRIMARY_PB_TBL );	if ( (TRUE 		== m_PendingBridgedResTbl[PBTbl][SeqNum].Used) &&		 (NET_FN(pIPMIReqHdr->NetFnLUN)  == NET_FN(m_PendingBridgedResTbl[PBTbl][SeqNum].ReqMsgHdr.NetFnLUN )) &&		 (pIPMIReqHdr->Cmd               == m_PendingBridgedResTbl[PBTbl][SeqNum].ReqMsgHdr.Cmd) &&		 (pIPMIReqHdr->ResAddr           == m_PendingBridgedResTbl[PBTbl][SeqNum].ReqMsgHdr.ResAddr)  )	{		//printf("---> RespondSendMessage/ m_PendingBridgedResTbl: PBTbl: %d, SeqNum %d, log222\n", PBTbl, SeqNum);		// int i;		// for(i=0;i<6;i++)		// 	printf("%#x ", ((uint8_t*)&m_PendingBridgedResTbl[PBTbl][SeqNum].ResMsgHdr.IPMIMsgHdr)[i]);		// printf("\n");		uint32_t tcnt = 0;		while(m_PendingBridgedResTbl[PBTbl][SeqNum].ResDataOk == 0)		{			usleep(1);			tcnt++;			if(tcnt > 100000)				{				printf("Warning: %s-%s Response data not ok!\n", __FILE__, __FUNCTION__);				break;	//100ms			}		}		if((m_PendingBridgedResTbl[PBTbl][SeqNum].OriginSrc == ORIGIN_INT_REQ) && (Status == STATUS_OK))		{			return;		}		if(m_PendingBridgedResTbl[PBTbl][SeqNum].DestQ == gFd_LanIfcQ)		{			memcpy (pIPMIResHdr, &m_PendingBridgedResTbl[PBTbl][SeqNum].ResMsgHdr.IPMIMsgHdr, sizeof (IPMIMsgHdr_T));			HdrOffset = sizeof(IPMIMsgHdr_T);		}		else if(m_PendingBridgedResTbl[PBTbl][SeqNum].DestQ == gFdUdsIfc)		{			memcpy (pIPMIResHdr, &m_PendingBridgedResTbl[PBTbl][SeqNum].ResMsgHdr.UDSMsgHdr, sizeof (IPMIUDSMsg_T));			HdrOffset = sizeof(IPMIUDSMsg_T);		}		else		{			//SwapIPMIMsgHdr ( pIPMIReqHdr, pIPMIResHdr);		   	//QueueFd = m_PendingBridgedResTbl[PBTbl][SeqNum].DestQ;			memcpy (pIPMIResHdr, &m_PendingBridgedResTbl[PBTbl][SeqNum].ResMsgHdr.IPMIMsgHdr, sizeof (IPMIMsgHdr_T));			HdrOffset = sizeof(IPMIMsgHdr_T);		}		 if (STATUS_OK == Status)		 {			if ( ( m_PendingBridgedResTbl[PBTbl][SeqNum].DestQ == gFd_PrimaryIpmbIfcQ) ||				 (m_PendingBridgedResTbl[PBTbl][SeqNum].DestQ == gFd_SecondaryIpmbIfcQ) ||				 (ORIGIN_SENDMSG != m_PendingBridgedResTbl[PBTbl][SeqNum].OriginSrc) )			{    				 return;			}							ResPkt.Data [HdrOffset] = CC_NORMAL;		 }		 else if (STATUS_FAIL == Status)		 {			ResPkt.Data [HdrOffset] = CC_NO_ACK_FROM_SLAVE;		 }		 else		 {			ResPkt.Data [HdrOffset] = CC_UNSPECIFIED_ERR;		 }		 ResPkt.Size = HdrOffset + 1 + 1; // IPMI Header + Completion Code + Second Checksum		 ResPkt.Cmd = pIPMIResHdr->Cmd;		 ResPkt.NetFnLUN = pIPMIReqHdr->NetFnLUN;		 ResPkt.Channel = pReq->Channel;		 //ResPkt.Socket = pReq->Socket;		 /* Calculate the Second CheckSum */		 ResPkt.Data[ResPkt.Size - 1] = CalculateCheckSum2 (ResPkt.Data, ResPkt.Size-1);		 ResPkt.Param = BRIDGING_REQUEST;		 if (m_PendingBridgedResTbl[PBTbl][SeqNum].DestQ == gFd_LanIfcQ)		 {			 QueueFd = gFd_LanResQ;		 }		 else if(m_PendingBridgedResTbl[PBTbl][SeqNum].DestQ == gFdUdsIfc)		 {		 	ResPkt.Size++;		 	ResPkt.Data[ResPkt.Size-1] = 0;		 	((IPMIUDSMsg_T*)&ResPkt.Data[0])->IPMIMsgLen = ResPkt.Size;		 	ResPkt.Socket = m_PendingBridgedResTbl[PBTbl][SeqNum].UDSSocket;		 	QueueFd = gFdUdsRes;		 }		 else		 {			QueueFd = m_PendingBridgedResTbl[PBTbl][SeqNum].DestQ;		 }		 if (STATUS_OK != Status)		 {			 m_PendingBridgedResTbl[PBTbl][SeqNum].Used = FALSE;			 m_PendingBridgedResTbl[PBTbl][SeqNum].ResDataOk = 0;		 }		 		 /* Post the data to Destination Interface queue */		 int i;		 printf("===> RespondSendMessage post to %d: ", QueueFd);		 for(i=0;i<ResPkt.Size;i++)		 	printf("%#x ", ResPkt.Data[i]);		 printf("\n");		 PostMsg (QueueFd, &ResPkt);	}}/***@fn PendingBridgeResTimerTask*@brief Sends the timeout message to response queue*          if the message does not turn out within send message timeout*@return none*/static voidPendingBridgeResTimerTask (void){	uint8_t		i;	uint8_t     PBTbl = PRIMARY_PB_TBL;	int 		QueueFd = 0;	printf("-> PendingBridgeResTimerTask\n");	/* Check for any pending responses */	for( PBTbl=0; PBTbl < MAX_PENDING_BRIDGE_TBL; PBTbl++)	{		for (i = 0; i < sizeof (m_PendingBridgedResTbl[0])/sizeof (m_PendingBridgedResTbl[0][0]); i++)		{			if (TRUE == m_PendingBridgedResTbl[PBTbl][i].Used)			{				m_PendingBridgedResTbl[PBTbl][i].TimeOut--;				if (0 == m_PendingBridgedResTbl[PBTbl][i].TimeOut)				{				   MsgPkt_T		Timeout;				   IPMIMsgHdr_T*   pIPMIMsgHdr  = (IPMIMsgHdr_T*) Timeout.Data;				   /* Fill the response packet */				   SwapIPMIMsgHdr (&m_PendingBridgedResTbl[PBTbl][i].ReqMsgHdr, pIPMIMsgHdr);				   // slog(LANQueueName,"%s%d",LAN_IFC_Q,BMCInst);				   // sprintf(PrimaryIPMBQueueName,"%s%d",IPMB_PRIMARY_IFC_Q,BMCInst);				   // sprintf(SecondaryIPMBQueueName,"%s%d",IPMB_SECONDARY_IFC_Q,BMCInst);				   // sprintf(SerialQueueName,"%s%d",SERIAL_IFC_Q,BMCInst);				   if(PBTbl == PRIMARY_PB_TBL)				   {					   pIPMIMsgHdr->ReqAddr = g_BMCInfo.PrimaryIPMBAddr;				   }				   else if(PBTbl == SECONDARY_PB_TBL)				   {					   pIPMIMsgHdr->ReqAddr = g_BMCInfo.SecondaryIPMBAddr;				   }				   else				   {					   printf("Invalid PBTbl\n");;//pIPMIMsgHdr->ReqAddr = pBMCInfo->IpmiConfig.BMCSlaveAddr;				   }				   Timeout.Data [sizeof(IPMIMsgHdr_T)] = CC_TIMEOUT;				   Timeout.Size = sizeof (IPMIMsgHdr_T) + 1 + 1; // IPMI Header + Completion Code + Second Checksum				   /* Calculate the Second CheckSum */				   Timeout.Data[Timeout.Size - 1] = CalculateCheckSum2 (Timeout.Data, Timeout.Size-1);				   Timeout.Param = BRIDGING_REQUEST;				   if (m_PendingBridgedResTbl[PBTbl][i].DestQ == gFd_LanIfcQ)				   {					   int j;					   for (j = Timeout.Size - 1; j >= 0; --j)					   {						   Timeout.Data [j+1] = Timeout.Data [j];					   }					   Timeout.Data[0] = m_PendingBridgedResTbl[PBTbl][i].SrcSessionHandle;					   Timeout.Size++;					   Timeout.Cmd = PAYLOAD_IPMI_MSG;					   QueueFd = gFd_LanIfcQ;					}				   // else if (0 == strcmp ((char *)m_PendingBridgedResTbl[PBTbl][i].DestQ, SerialQueueName))				   // {					  //  int j;					  //  for (j = Timeout.Size - 1; j >= 0; --j)					  //  {						 //   Timeout.Data [j+1] = Timeout.Data [j];					  //  }					  //  Timeout.Data[0] = m_PendingBridgedResTbl[PBTbl][i].SrcSessionHandle;					  //  Timeout.Size++;					  //  Timeout.Cmd = PAYLOAD_IPMI_MSG;					  //  strcpy(QueueName, SERIAL_IFC_Q);				   // }				 //   else if (g_BMCInfo.IpmiConfig.PrimaryIPMBSupport == 1 && m_PendingBridgedResTbl[PBTbl][i].DestQ == gFd_PrimaryIpmbIfcQ)					// {					//    int j;					//    for (j = Timeout.Size - 1; j >= 0; --j)					//    {					// 	   Timeout.Data [j + sizeof (IPMIMsgHdr_T) + 1] = Timeout.Data [j];					//    }					//    memcpy (Timeout.Data, &m_PendingBridgedResTbl[PBTbl][i].ResMsgHdr, sizeof (IPMIMsgHdr_T));					//    Timeout.Data[sizeof (IPMIMsgHdr_T)] = CC_NORMAL;					//    Timeout.Size++;					//    QueueFd = gFd_PrimaryIpmbIfcQ;					//  }					//  else if (g_BMCInfo.IpmiConfig.SecondaryIPMBSupport == 1 && m_PendingBridgedResTbl[PBTbl][i].DestQ == gFd_SecondaryIpmbIfcQ)					//  {					// 	int j;					// 	for (j = Timeout.Size - 1; j >= 0; --j)					// 	{					// 		Timeout.Data [j + sizeof (IPMIMsgHdr_T) + 1] = Timeout.Data [j];					// 	}					// 	memcpy (Timeout.Data, &m_PendingBridgedResTbl[PBTbl][i].ResMsgHdr.IPMIMsgHdr, sizeof (IPMIMsgHdr_T));					// 	Timeout.Data[sizeof (IPMIMsgHdr_T)] = CC_NORMAL;					// 	Timeout.Size++;					// 	QueueFd = gFd_SecondaryIpmbIfcQ;					//  }					 else if (m_PendingBridgedResTbl[PBTbl][i].DestQ = gFdUdsIfc)					 {					 	printf("---> UDS pending bridge TimeOut\n");						 int j;						 UDSSessionTbl_T *pUDSSessionInfo = NULL;						 for (j = sizeof (IPMIMsgHdr_T); j < Timeout.Size ;j++)						 {							Timeout.Data [j + sizeof (IPMIUDSMsg_T)-sizeof (IPMIMsgHdr_T)] = Timeout.Data [j];						 }						 Timeout.Size = Timeout.Size + sizeof (IPMIUDSMsg_T)- sizeof (IPMIMsgHdr_T);						 						 m_PendingBridgedResTbl[PBTbl][i].ResMsgHdr.UDSMsgHdr.IPMIMsgLen = Timeout.Size;						 memcpy (Timeout.Data, &m_PendingBridgedResTbl[PBTbl][i].ResMsgHdr.UDSMsgHdr, sizeof (IPMIUDSMsg_T));						 Timeout.NetFnLUN = m_PendingBridgedResTbl[PBTbl][i].ResMsgHdr.UDSMsgHdr.NetFnLUN;						 Timeout.SessionID = m_PendingBridgedResTbl[PBTbl][i].ResMsgHdr.UDSMsgHdr.SessionID;						 Timeout.Cmd = m_PendingBridgedResTbl[PBTbl][i].ResMsgHdr.UDSMsgHdr.Cmd;						 						 pUDSSessionInfo = GetUDSSessionInfo (UDS_SESSION_ID_INFO,&Timeout.SessionID);						 if(pUDSSessionInfo != NULL)						 {							 Timeout.Socket = pUDSSessionInfo->UDSSocket;						 }						 QueueFd = m_PendingBridgedResTbl[PBTbl][i].DestQ;					 }					 else 					 {						int j;						for (j = Timeout.Size - 1; j >= 0; --j)						{						   Timeout.Data [j + sizeof (IPMIMsgHdr_T) + 1] = Timeout.Data [j];						}						memcpy (Timeout.Data, &m_PendingBridgedResTbl[PBTbl][i].ResMsgHdr.IPMIMsgHdr, sizeof (IPMIMsgHdr_T));						Timeout.Data[sizeof (IPMIMsgHdr_T)] = CC_TIMEOUT;						QueueFd = m_PendingBridgedResTbl[PBTbl][i].DestQ;					 }					  /* Post the data to Destination Interface queue */					  PostMsg (QueueFd, &Timeout);					  m_PendingBridgedResTbl[PBTbl][i].Used = FALSE;					  printf( "MsgHndlr: clean pending index = %d.\n", i );				}		   }		}	}}/***@fn PendingSeqNoTimerTask*@brief Timertask which helpful in IPMB sequence number validation*@return none*/static voidPendingSeqNoTimerTask (void){	uint8_t	i,j;	printf("-> PendingSeqNoTimerTask\n");	/* Check for any Sequence Number expiraied */	for (i = 0; i < sizeof (m_PendingSeqNoTbl)/sizeof (m_PendingSeqNoTbl[0]); i++)	{		for (j = 0; j < sizeof (m_PendingSeqNoTbl[0])/sizeof (m_PendingSeqNoTbl[0][0]); j++)		{			if (TRUE == m_PendingSeqNoTbl[i][j].Used)			{				m_PendingSeqNoTbl[i][j].TimeOut--;				if (0 == m_PendingSeqNoTbl[i][j].TimeOut)				{					m_PendingSeqNoTbl[i][j].Used = FALSE;				}			}		}	}}/***@fn SwapIPMIMsgHdr*@brief Swaps the header and copies into response*@param pIPMIMsgReq Header of the Request*@param pIPMIMsgRes Header of the response*@return none*/voidSwapIPMIMsgHdr (IPMIMsgHdr_T* pIPMIMsgReq, IPMIMsgHdr_T* pIPMIMsgRes){	pIPMIMsgRes->ResAddr   = pIPMIMsgReq->ReqAddr;	pIPMIMsgRes->NetFnLUN  = (pIPMIMsgReq->NetFnLUN & 0xFC) + 0x04;	pIPMIMsgRes->NetFnLUN |= pIPMIMsgReq->RqSeqLUN & 0x03;	/* Calculate the Checksum for above two bytes */	pIPMIMsgRes->ChkSum   = (~(pIPMIMsgRes->ResAddr + pIPMIMsgRes->NetFnLUN) + 1);	pIPMIMsgRes->ReqAddr  = pIPMIMsgReq->ResAddr;	pIPMIMsgRes->RqSeqLUN = (pIPMIMsgReq->RqSeqLUN & 0xFC);	pIPMIMsgRes->RqSeqLUN |= (pIPMIMsgReq->NetFnLUN & 0x03);	pIPMIMsgRes->Cmd = pIPMIMsgReq->Cmd;	return;}/** * *@fn Swap UDSIPMIMsg * *@brief Swaps the header and copies into response * *@param pIPMIMsgReq Header of the Request * *@param pIPMIMsgRes Header of the response * *@return none * */voidSwapUDSIPMIMsg ( MsgPkt_T* pIPMIMsgReq,  MsgPkt_T* pIPMIMsgRes){	IPMIUDSMsg_T *pIPMIUDSMsgRes = (IPMIUDSMsg_T *)&pIPMIMsgRes->Data[0];	IPMIUDSMsg_T *pIPMIUDSMsgReq = (IPMIUDSMsg_T *)&pIPMIMsgReq->Data[0];	pIPMIMsgRes->NetFnLUN = pIPMIMsgReq->NetFnLUN;//	pIPMIMsgRes->Privilege = pIPMIMsgReq->Privilege;	pIPMIMsgRes->Cmd = pIPMIMsgReq->Cmd;	pIPMIMsgRes->Channel = pIPMIMsgReq->Channel;	pIPMIMsgRes->SessionID   = pIPMIMsgReq->SessionID;	pIPMIMsgRes->Socket = pIPMIMsgReq->Socket;	pIPMIUDSMsgRes->NetFnLUN = pIPMIMsgReq->NetFnLUN;//	pIPMIUDSMsgRes->Privilege = pIPMIMsgReq->Privilege;	pIPMIUDSMsgRes->Cmd = pIPMIMsgReq->Cmd;	pIPMIUDSMsgRes->ChannelNum = pIPMIMsgReq->Channel;	pIPMIUDSMsgRes->SessionID = pIPMIMsgReq->SessionID;	//pIPMIUDSMsgRes->AuthFlag = pIPMIUDSMsgReq->AuthFlag;	pIPMIUDSMsgRes->IPMIMsgLen = pIPMIMsgRes->Size;	//	strcpy( (char *)pIPMIUDSMsgRes->UserName, (char *)pIPMIUDSMsgReq->UserName);//	memcpy(pIPMIUDSMsgRes->IPAddr, pIPMIUDSMsgReq->IPAddr, 16);  	return;}
 |