123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499 |
- /*
- * Brief: Implement IPMB send and receive function in this file, include primary IPMB and secondary IPMB.
- * Author: Jimbo_Zhang@outlook.com
- * Date: 2019-9-9
- */
- /* Standard includes. */
- #include <stdio.h>
- #include <stdint.h>
- #include <string.h>
- #include <errno.h>
- #include <pthread.h>
- #include <fcntl.h>
- #include <sys/socket.h>
- #include "com_IPMI_LANIfc.h"
- #include "com_IPMI_RMCP.h"
- #include "RMCP.h"
- #include "LANIfc.h"
- #include "com_IPMIDefs.h"
- #include "RMCP.h"
- #include "MD.h"
- #include <netdb.h> /* getaddrinfo(3) et al. */
- #include <netinet/in.h> /* sockaddr_in & sockaddr_in6 definition. */
- #include <net/if.h>
- #include <sys/prctl.h>
- #include "main.h"
- #include "Session.h"
- #include "com_IPMI_SDR.h"
- #include "com_IPMI_Storage.h"
- #include "SDR.h"
- #include <sys/syscall.h> /*此头必须带上*/
- pid_t gettid()
- {
- return syscall(SYS_gettid); /*这才是内涵*/
- }
- //static int sendIPMBPkt(uint32_t ipmb_bus, uint8_t* i2c_send_buf, uint8_t size);
- static uint8_t ValidateIPMBChkSums ( uint8_t* Data, uint8_t Size);
- static void ProcessIPMBReq ( MsgPkt_T* pReq);
- uint8_t IsResponseMatch (MsgPkt_T* pReq, MsgPkt_T* pRes);
- static void* RecvIPMBPkt (void *pArg);
- int gFd_PrimaryIpmbIfcQ, gFd_PrimaryIpmbResQ;
- int gFd_SecondaryIpmbIfcQ, gFd_SecondaryIpmbResQ;
- int gFd_Primary, gFd_Secondary;
- pthread_mutex_t primary_mutex, secondary_mutex;
- /*!
- \brief IPMB Task. Generating primary_IPMB task and secondary_IPMB task in this task.
- \param: 0: primary ipmb, 1: secondary ipmb
- \retval none
- */
- void *IPMBIfcTask(void *Param)
- {
- // int i;
- MsgPkt_T RcvMsgPkt;
- uint8_t dev_name[10] = {0};
- uint8_t IPMB_IFC_Q[32] = {0};
- uint8_t IPMB_RES_Q[32] = {0};
- uint8_t OwnerAddr;
- int fd_IpmbDev;
- int fd_IpmbIfcQ, fd_IpmbResQ;
- uint8_t ipmbSelect = *(uint8_t*)Param;
- int RetVal;
- pthread_mutex_t *pMutex;
-
- //printf("ipmbSelect: %d\n", ipmbSelect);
- //Primary IPMB
- if((ipmbSelect == 0) && g_BMCInfo.IpmiConfig.PrimaryIPMBSupport)
- {
- printf("Primary IPMBIfcTask start...\n");
- strcpy(IPMB_IFC_Q, PRIMARY_IPMB_IFC_Q);
- strcpy(IPMB_RES_Q, PRIMARY_IPMB_RES_Q);
- sprintf(dev_name, "/dev/i2c%d", g_BMCInfo.IpmiConfig.PrimaryIPMBBus);
- OwnerAddr = g_BMCInfo.PrimaryIPMBAddr;
- pMutex = &primary_mutex;
- }
- //Secondary IPMB
- else if((ipmbSelect == 1) && g_BMCInfo.IpmiConfig.SecondaryIPMBSupport)
- {
- printf("Secondary IPMBIfcTask start...\n");
- strcpy(IPMB_IFC_Q, SECONDARY_IPMB_IFC_Q);
- strcpy(IPMB_RES_Q, SECONDARY_IPMB_RES_Q);
- sprintf(dev_name, "/dev/i2c%d", g_BMCInfo.IpmiConfig.SecondaryIPMBBus);
- OwnerAddr = g_BMCInfo.SecondaryIPMBAddr;
- pMutex = &secondary_mutex;
- }
- else
- {
- printf("Invalid param! %d\n", ipmbSelect);
- return (void *)-1;
- }
- //create IPMB_IFC_Q
- if(-1 != access(IPMB_IFC_Q, F_OK))
- {
- remove(IPMB_IFC_Q);
- }
- if(0 != mkfifo (IPMB_IFC_Q, 0777))
- {
- printf("%s: Create %s fifo failed! %s\n", __FUNCTION__, IPMB_IFC_Q, strerror(errno));
- return (void*)-1;
- }
- fd_IpmbIfcQ = open (IPMB_IFC_Q, O_RDWR);
- if(-1 == fd_IpmbIfcQ)
- {
- printf("%s: Open %s fifo failed! %s\n", __FUNCTION__, IPMB_IFC_Q, strerror(errno));
- return (void*)-1;
- }
- //create IPMB_RES_Q
- if(-1 != access(IPMB_RES_Q, F_OK))
- {
- remove(IPMB_RES_Q);
- }
- if(0 != mkfifo (IPMB_RES_Q, 0777))
- {
- printf("%s: Create %s fifo failed! %s\n", __FUNCTION__, IPMB_RES_Q, strerror(errno));
- return (void*)-1;
- }
- fd_IpmbResQ = open (IPMB_RES_Q, O_RDWR);
- if(-1 == fd_IpmbResQ)
- {
- printf("%s: Open %s fifo failed! %s\n", __FUNCTION__, IPMB_RES_Q, strerror(errno));
- return (void*)-1;
- }
- fd_IpmbDev = open (dev_name, O_RDWR);
- if(-1 == fd_IpmbDev)
- {
- printf("%s: Open IPMB failed! %s\n", __FUNCTION__, strerror(errno));
- return (void*)-1;
- }
- //set IPMB address
- if(0 != stm32_i2c_set_addr(fd_IpmbDev, OwnerAddr))
- printf("Set ipmb address fail.\n");
- if(ipmbSelect == 0)
- {
- gFd_PrimaryIpmbIfcQ = fd_IpmbIfcQ;
- gFd_PrimaryIpmbResQ = fd_IpmbResQ;
- gFd_Primary = fd_IpmbDev;
- }
- else if(ipmbSelect == 1)
- {
- gFd_SecondaryIpmbIfcQ = fd_IpmbIfcQ;
- gFd_SecondaryIpmbResQ = fd_IpmbResQ;
- gFd_Secondary = fd_IpmbDev;
- }
- pthread_mutex_init(pMutex, NULL);
- /*Create a thread to recv IPMB Pkt */
- gThreadIndex++;
- if(0 != pthread_create(&gThreadIDs[gThreadIndex],NULL,RecvIPMBPkt,Param))
- {
- printf("%s: Create RecvIPMBPkt thread failed! %s\n", __FUNCTION__, strerror(errno));
- return (void *)-1;
- }
- while(1)
- {
- while(GetMsg(fd_IpmbIfcQ, &RcvMsgPkt, WAIT_INFINITE) != 0);
-
- switch(RcvMsgPkt.Param)
- {
- case PARAM_REQUEST:
- ProcessIPMBReq (&RcvMsgPkt);
- break;
- case PARAM_BRIDGE:
- /* Send the response */
- if(RcvMsgPkt.Channel == PRIMARY_IPMB_CHANNEL)
- {
- RetVal = stm32_i2c_master_write(gFd_Primary, RcvMsgPkt.Data[0], &RcvMsgPkt.Data[1], RcvMsgPkt.Size-1);
- //printf("PriTx: ");
- }
- else if(RcvMsgPkt.Channel == SECONDARY_IPMB_CHANNEL)
- {
- RetVal = stm32_i2c_master_write(gFd_Secondary, RcvMsgPkt.Data[0], &RcvMsgPkt.Data[1], RcvMsgPkt.Size-1);
- //printf("SecTx: ");
- }
- else
- {
- printf("IPMBIfc.c: IPMB channel error. %#x\r\n", RcvMsgPkt.Channel);
- }
- // int i;
- // for(i=0;i<RcvMsgPkt.Size;i++)
- // printf("%02x ", RcvMsgPkt.Data[i]);
- // printf("\n");
- if (RetVal < 0)
- {
- printf ("IPMBIfc.c : Unable to send a IPMI Bridge Message\n");
- RespondSendMessage (&RcvMsgPkt, STATUS_FAIL);
- }
- else
- {
- RespondSendMessage (&RcvMsgPkt, STATUS_OK);
- }
-
- break;
- default:
- printf("Unknow message param %#x\r\n", RcvMsgPkt.Param);
- break;
- }
-
- }
- }
- /**
- * @brief Process the request posted by IPMB driver.
- * @param pReq - Request message pointer.
- **/
- static void
- ProcessIPMBReq ( MsgPkt_T* pReq)
- {
- MsgPkt_T ResPkt;
- uint8_t ReqLen;
- IPMIMsgHdr_T* pIPMIMsgReq = (IPMIMsgHdr_T*) pReq->Data;
-
- int RetVal = 0;
- ReqLen = pReq->Size;
-
- /* Validate Checksums */
- if (TRUE != ValidateIPMBChkSums ((uint8_t*)pIPMIMsgReq, ReqLen))
- {
- printf ("IPMBIfc.c : IPMB Checksum validation failed\r\n");
- return;
- }
- pReq->Param = PARAM_IFC;
- pReq->Cmd = pIPMIMsgReq->Cmd;
- pReq->NetFnLUN = pIPMIMsgReq->NetFnLUN;
- if(pReq->Channel == PRIMARY_IPMB_CHANNEL)
- pReq->SrcQ = gFd_PrimaryIpmbResQ;
- else
- pReq->SrcQ = gFd_SecondaryIpmbResQ;
-
- if(0 == ValidateMsgHdr(pReq))
- {
- /* Post the message to message handler Task */
- if (0 != PostMsg (gFd_MsgHndlrIfc, pReq))
- {
- printf("IPMB post message to MsgHndlrTask fail!\n");;
- }
- }
- else
- {
- //printf("Bridge response to Originator\n");
- return;
- }
- /* Post the message to message handler Task */
- //PostMsg (gFd_MsgHndlrIfc, pReq);
-
- if(pReq->ResTimeOut < 1) pReq->ResTimeOut = 10;
- do
- {
- if(pReq->Channel == PRIMARY_IPMB_CHANNEL)
- {
- RetVal = GetMsg (gFd_PrimaryIpmbResQ, &ResPkt, pReq->ResTimeOut);
- if((pReq->Cmd == CMD_GET_SDR) && (pReq->NetFnLUN == (NETFN_STORAGE<<2))
- && (pReq->Data[4+6] == 5))
- {
- ResPkt.Data[3+6] = g_BMCInfo.PrimaryIPMBAddr;
- ResPkt.Data[ResPkt.Size-1] = CalculateCheckSum (ResPkt.Data, ResPkt.Size-1);
- }
- }
- else
- {
- RetVal = GetMsg (gFd_SecondaryIpmbResQ, &ResPkt, pReq->ResTimeOut);
- //为传感器的owner ID打的补丁
- if((pReq->Cmd == CMD_GET_SDR) && (pReq->NetFnLUN == (NETFN_STORAGE<<2))
- && (pReq->Data[4+6] == 5))
- {
- ResPkt.Data[3+6] = g_BMCInfo.SecondaryIPMBAddr;
- ResPkt.Data[ResPkt.Size-1] = CalculateCheckSum (ResPkt.Data, ResPkt.Size-1);
- }
- }
- }while(!RetVal && !IsResponseMatch(pReq, &ResPkt) );
-
- if (0 != RetVal)
- {
- printf("Warning: Process IPMB request fail, return timeout.\r\n");
- ResPkt.Param = PARAM_NORMAL_RESPONSE;
- ResPkt.Size = sizeof(IPMIMsgHdr_T)+2;
-
- SwapIPMIMsgHdr(((IPMIMsgHdr_T*)pReq->Data), ((IPMIMsgHdr_T*)ResPkt.Data));
- ResPkt.Data[sizeof(IPMIMsgHdr_T)] = CC_TIMEOUT;
- ResPkt.Data[sizeof(IPMIMsgHdr_T)+1] = CalculateCheckSum2(ResPkt.Data, sizeof(IPMIMsgHdr_T)+1);
- }
- /* If its not normal IPMI Response just return */
- if (PARAM_NO_RESPONSE == ResPkt.Param)
- {
- printf ("IPMBIfc.c : IPMB request packet dropped, not processed\n");
- return;
- }
- //usleep(2000);
- /* Send the response */
- if(pReq->Channel == PRIMARY_IPMB_CHANNEL)
- {
- pthread_mutex_lock(&primary_mutex);
- RetVal = stm32_i2c_master_write(gFd_Primary, ResPkt.Data[0], &ResPkt.Data[1], ResPkt.Size-1);
- pthread_mutex_unlock(&primary_mutex);
- //printf("PriTx: ");
- }
- else if(pReq->Channel == SECONDARY_IPMB_CHANNEL)
- {
- pthread_mutex_lock(&secondary_mutex);
- RetVal = stm32_i2c_master_write(gFd_Secondary, ResPkt.Data[0], &ResPkt.Data[1], ResPkt.Size-1);
- pthread_mutex_unlock(&secondary_mutex);
- //printf("SecTx: ");
- }
- else
- {
- printf("IPMBIfc.c: IPMB channel error. %#x\r\n", pReq->Channel);
- }
- // int i;
- // for(i=0;i<ResPkt.Size;i++)
- // printf("%02x ", ResPkt.Data[i]);
- // printf("\n");
-
- if (0 != RetVal)
- {
- printf ("IPMBIfc.c : Unable to send a IPMI Response\n");
- }
- return;
- }
- /**
- * @brief Validate IPMB Checksums.
- * @param Data - Buffer to be validated.
- * @param Size - Size of the buffer.
- * @return TRUE if valid, FALSE if error.
- **/
- static uint8_t ValidateIPMBChkSums ( uint8_t* Data, uint8_t Size)
- {
- uint8_t i;
- uint8_t chksum;
- /* Check IPMB message min size */
- if (Size < MIN_IPMB_MSG_LENGTH)
- {
- printf("IPMBIfc.c: Invalid IPMB Message Length\r\n");
- return FALSE;
- }
- /* Validate the checksum1 */
- chksum = 0;
- for (i = 0; i < 3; i++)
- {
- chksum += *(Data + i);
- }
- if (chksum != 0)
- {
-
- printf ("IPMBIfc.c: Invalid checksum 1, size = %d\n",Size);
- for(i = 0; i < Size;i++)
- printf("%x ",Data[i]);
- printf("\n");
- return FALSE;
- }
- /* Validate the checksum2 */
- chksum = 0;
- for (i = 3; i < Size; i++)
- {
- chksum += *(Data + i);
- }
- if (chksum != 0)
- {
-
- printf("IPMBIfc.c: Invalid checksum 2, size = %d\n",Size);
- for(i = 0; i < Size;i++)
- printf("%x ",Data[i]);
- printf("\n");
-
- return FALSE;
- }
- return TRUE;
- }
- /*-----------------------------------------------------
- * @fn IsResponseMatch
- * @brief Checks if the Response Message corresponds to
- * the Request Message
- *
- * @param pReq : IPMI Request Message Packet
- * @param pRes : IPMI Response Message Packet
- *
- * @return 1 if match
- * 0 if mismatch
- *----------------------------------------------------*/
- uint8_t IsResponseMatch (MsgPkt_T* pReq, MsgPkt_T* pRes)
- {
- if( ( ((((IPMIMsgHdr_T*)pRes->Data)->RqSeqLUN) >> 2) != ((((IPMIMsgHdr_T*)pReq->Data)->RqSeqLUN) >> 2) ) &&
- ( (pReq->NetFnLUN & 0x4) && (PARAM_NO_RESPONSE != pRes->Param) ) )
- {
- return FALSE;
- }
-
- return TRUE;
- }
- /**
- * @fn RecvIPMBPkt
- * @brief This function receives IPMB request packet and post the message to
- * IPMB interface queue
- **/
- static void* RecvIPMBPkt (void *Param)
- {
- MsgPkt_T IPMBReqPkt;
- int IPMBSlaveFd;
- int retval;
- uint8_t ipmbSelect = *(uint8_t*)Param;
- int i;
- prctl(PR_SET_NAME, __FUNCTION__, 0, 0, 0);
- int curThreadIndex = 0;
- pthread_mutex_t *pMutex;
- memset(&IPMBReqPkt,0,sizeof(MsgPkt_T));
- if(0 == ipmbSelect)
- {
- printf ("Primary IPMB Receiver Started...\n");
- IPMBReqPkt.Data [0] = g_BMCInfo.PrimaryIPMBAddr;
- IPMBReqPkt.Channel = PRIMARY_IPMB_CHANNEL;
- IPMBSlaveFd = gFd_Primary;
- pMutex = &primary_mutex;
- //printf("Primary: %p\n", RecvIPMBPkt);
- }
- else if(1 == ipmbSelect)
- {
- printf ("Secondary IPMB Receiver Started...\n");
- IPMBReqPkt.Data [0] = g_BMCInfo.SecondaryIPMBAddr;
- IPMBReqPkt.Channel = SECONDARY_IPMB_CHANNEL;
- IPMBSlaveFd = gFd_Secondary;
- pMutex = &secondary_mutex;
- //printf("Secondary: %p\n", RecvIPMBPkt);
- }
- /* Loop forever */
- while (1)
- {
- //printf("ppid: %d, pid: %d, tid: %d, i: %d, ipmbSelect: %d\n", getppid(), getpid(), gettid(), i++, ipmbSelect);
- pthread_mutex_lock(pMutex);
- pthread_mutex_unlock(pMutex);
- retval = stm32_i2c_slave_recv(IPMBSlaveFd, &IPMBReqPkt.Data[1]);
- if( retval > 5)
- {
- IPMBReqPkt.Param = PARAM_REQUEST;
- IPMBReqPkt.Size = retval + 1; /* +1 to include BMC Slave address */
- /* Post the IPMB Request message to IPMBIfc Queue */
- if(ipmbSelect == 0)
- {
- if (0 != PostMsg (gFd_PrimaryIpmbIfcQ, &IPMBReqPkt))
- {
- printf ("IPMBIfc.c : Error posting message to IPMBIfc_Q\n");
- }
- }
- else
- {
- if (0 != PostMsg (gFd_SecondaryIpmbIfcQ, &IPMBReqPkt))
- {
- printf ("IPMBIfc.c : Error posting message to IPMBIfc_Q\n");
- }
- }
- // int cnt;
- // if(0 == ipmbSelect)
- // printf("\nPriRx: ");
- // else
- // printf("\nSecRx: ");
- // for(cnt=0;cnt < IPMBReqPkt.Size; cnt++)
- // printf("%02x ", IPMBReqPkt.Data[cnt]);
- // printf("\n");
- }
- }
- return (void*)-1;
- }
|