IPMBIfc.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432
  1. /*
  2. * Brief: Implement IPMB send and receive function in this file, include primary IPMB and secondary IPMB.
  3. * Author: Jimbo_Zhang@outlook.com
  4. * Date: 2019-9-9
  5. */
  6. /* Standard includes. */
  7. #include <stdio.h>
  8. #include <stdint.h>
  9. #include <string.h>
  10. #include <errno.h>
  11. #include <pthread.h>
  12. #include <fcntl.h>
  13. #include <sys/socket.h>
  14. #include "com_IPMI_LANIfc.h"
  15. #include "com_IPMI_RMCP.h"
  16. #include "RMCP.h"
  17. #include "LANIfc.h"
  18. #include "com_IPMIDefs.h"
  19. #include "RMCP.h"
  20. #include "MD.h"
  21. #include <netdb.h> /* getaddrinfo(3) et al. */
  22. #include <netinet/in.h> /* sockaddr_in & sockaddr_in6 definition. */
  23. #include <net/if.h>
  24. #include <sys/prctl.h>
  25. #include "main.h"
  26. #include "Session.h"
  27. #include "com_IPMI_SDR.h"
  28. #include "com_IPMI_Storage.h"
  29. #include "SDR.h"
  30. //static int sendIPMBPkt(uint32_t ipmb_bus, uint8_t* i2c_send_buf, uint8_t size);
  31. static uint8_t ValidateIPMBChkSums ( uint8_t* Data, uint8_t Size);
  32. static void ProcessIPMBReq ( MsgPkt_T* pReq);
  33. uint8_t IsResponseMatch (MsgPkt_T* pReq, MsgPkt_T* pRes);
  34. static void* RecvIPMBPkt (void *pArg);
  35. int gFd_PrimaryIpmbIfcQ, gFd_PrimaryIpmbResQ;
  36. int gFd_SecondaryIpmbIfcQ, gFd_SecondaryIpmbResQ;
  37. int gFd_Primary, gFd_Secondary;
  38. /*!
  39. \brief IPMB Task. Generating primary_IPMB task and secondary_IPMB task in this task.
  40. \param: 0: primary ipmb, 1: secondary ipmb
  41. \retval none
  42. */
  43. void *IPMBIfcTask(void *Param)
  44. {
  45. // int i;
  46. MsgPkt_T RcvMsgPkt;
  47. uint8_t dev_name[10] = {0};
  48. uint8_t IPMB_IFC_Q[32] = {0};
  49. uint8_t IPMB_RES_Q[32] = {0};
  50. uint8_t OwnerAddr;
  51. int fd_IpmbDev;
  52. int fd_IpmbIfcQ, fd_IpmbResQ;
  53. uint8_t ipmbSelect = *(uint8_t*)Param;
  54. int RetVal;
  55. //printf("ipmbSelect: %d\n", ipmbSelect);
  56. //Primary IPMB
  57. if((ipmbSelect == 0) && g_BMCInfo.IpmiConfig.PrimaryIPMBSupport)
  58. {
  59. printf("Primary IPMBIfcTask start...\n");
  60. strcpy(IPMB_IFC_Q, PRIMARY_IPMB_IFC_Q);
  61. strcpy(IPMB_RES_Q, PRIMARY_IPMB_RES_Q);
  62. sprintf(dev_name, "/dev/i2c%d", g_BMCInfo.IpmiConfig.PrimaryIPMBBus);
  63. OwnerAddr = g_BMCInfo.IpmiConfig.PrimaryIPMBAddr;
  64. }
  65. //Secondary IPMB
  66. else if((ipmbSelect == 1) && g_BMCInfo.IpmiConfig.SecondaryIPMBSupport)
  67. {
  68. printf("Secondary IPMBIfcTask start...\n");
  69. strcpy(IPMB_IFC_Q, SECONDARY_IPMB_IFC_Q);
  70. strcpy(IPMB_RES_Q, SECONDARY_IPMB_RES_Q);
  71. sprintf(dev_name, "/dev/i2c%d", g_BMCInfo.IpmiConfig.SecondaryIPMBBus);
  72. OwnerAddr = g_BMCInfo.IpmiConfig.SecondaryIPMBAddr;
  73. }
  74. else
  75. {
  76. printf("Invalid param! %d\n", ipmbSelect);
  77. return (void *)-1;
  78. }
  79. //create IPMB_IFC_Q
  80. if(-1 != access(IPMB_IFC_Q, F_OK))
  81. {
  82. remove(IPMB_IFC_Q);
  83. }
  84. if(0 != mkfifo (IPMB_IFC_Q, 0777))
  85. {
  86. printf("%s: Create %s fifo failed! %s\n", __FUNCTION__, IPMB_IFC_Q, strerror(errno));
  87. return (void*)-1;
  88. }
  89. fd_IpmbIfcQ = open (IPMB_IFC_Q, O_RDWR);
  90. if(-1 == fd_IpmbIfcQ)
  91. {
  92. printf("%s: Open %s fifo failed! %s\n", __FUNCTION__, IPMB_IFC_Q, strerror(errno));
  93. return (void*)-1;
  94. }
  95. //create IPMB_RES_Q
  96. if(-1 != access(IPMB_RES_Q, F_OK))
  97. {
  98. remove(IPMB_RES_Q);
  99. }
  100. if(0 != mkfifo (IPMB_RES_Q, 0777))
  101. {
  102. printf("%s: Create %s fifo failed! %s\n", __FUNCTION__, IPMB_RES_Q, strerror(errno));
  103. return (void*)-1;
  104. }
  105. fd_IpmbResQ = open (IPMB_RES_Q, O_RDWR);
  106. if(-1 == fd_IpmbResQ)
  107. {
  108. printf("%s: Open %s fifo failed! %s\n", __FUNCTION__, IPMB_RES_Q, strerror(errno));
  109. return (void*)-1;
  110. }
  111. fd_IpmbDev = open (dev_name, O_RDWR);
  112. if(-1 == fd_IpmbDev)
  113. {
  114. printf("%s: Open IPMB failed! %s\n", __FUNCTION__, strerror(errno));
  115. return (void*)-1;
  116. }
  117. //set IPMB address
  118. if(0 != stm32_i2c_set_addr(fd_IpmbDev, OwnerAddr))
  119. printf("Set ipmb address fail.\n");
  120. if(ipmbSelect == 0)
  121. {
  122. gFd_PrimaryIpmbIfcQ = fd_IpmbIfcQ;
  123. gFd_PrimaryIpmbResQ = fd_IpmbResQ;
  124. gFd_Primary = fd_IpmbDev;
  125. }
  126. else if(ipmbSelect == 1)
  127. {
  128. gFd_SecondaryIpmbIfcQ = fd_IpmbIfcQ;
  129. gFd_SecondaryIpmbResQ = fd_IpmbResQ;
  130. gFd_Secondary = fd_IpmbDev;
  131. }
  132. /*Create a thread to recv IPMB Pkt */
  133. gThreadIndex++;
  134. if(0 != pthread_create(&gThreadIDs[gThreadIndex],NULL,RecvIPMBPkt,Param))
  135. {
  136. printf("%s: Create RecvIPMBPkt thread failed! %s\n", __FUNCTION__, strerror(errno));
  137. return (void *)-1;
  138. }
  139. while(1)
  140. {
  141. while(GetMsg(fd_IpmbIfcQ, &RcvMsgPkt, WAIT_INFINITE) != 0);
  142. switch(RcvMsgPkt.Param)
  143. {
  144. case PARAM_REQUEST:
  145. ProcessIPMBReq (&RcvMsgPkt);
  146. break;
  147. case PARAM_BRIDGE:
  148. printf("---> BRIDGING_REQUEST, channel: %d\n", RcvMsgPkt.Channel);
  149. int i;
  150. for(i=0;i<RcvMsgPkt.Size;i++)
  151. printf("%#x ", RcvMsgPkt.Data[i]);
  152. printf("\n");
  153. /* Send the response */
  154. if(RcvMsgPkt.Channel == PRIMARY_IPMB_CHANNEL)
  155. {
  156. RetVal = stm32_i2c_master_write(gFd_Primary, RcvMsgPkt.Data[0], &RcvMsgPkt.Data[1], RcvMsgPkt.Size-1);
  157. }
  158. else if(RcvMsgPkt.Channel == SECONDARY_IPMB_CHANNEL)
  159. {
  160. RetVal = stm32_i2c_master_write(gFd_Secondary, RcvMsgPkt.Data[0], &RcvMsgPkt.Data[1], RcvMsgPkt.Size-1);
  161. }
  162. else
  163. {
  164. printf("IPMBIfc.c: IPMB channel error. %#x\r\n", RcvMsgPkt.Channel);
  165. }
  166. if (RetVal < 0)
  167. {
  168. printf ("IPMBIfc.c : Unable to send a IPMI Bridge Message\n");
  169. RespondSendMessage (&RcvMsgPkt, STATUS_FAIL);
  170. }
  171. else
  172. {
  173. RespondSendMessage (&RcvMsgPkt, STATUS_OK);
  174. }
  175. break;
  176. default:
  177. printf("Unknow message param %#x\r\n", RcvMsgPkt.Param);
  178. break;
  179. }
  180. }
  181. }
  182. /**
  183. * @brief Process the request posted by IPMB driver.
  184. * @param pReq - Request message pointer.
  185. **/
  186. static void
  187. ProcessIPMBReq ( MsgPkt_T* pReq)
  188. {
  189. MsgPkt_T ResPkt;
  190. uint8_t ReqLen;
  191. IPMIMsgHdr_T* pIPMIMsgReq = (IPMIMsgHdr_T*) pReq->Data;
  192. int RetVal = 0;
  193. ReqLen = pReq->Size;
  194. /* Validate Checksums */
  195. if (TRUE != ValidateIPMBChkSums ((uint8_t*)pIPMIMsgReq, ReqLen))
  196. {
  197. printf ("IPMBIfc.c : IPMB Checksum validation failed\r\n");
  198. return;
  199. }
  200. pReq->Param = PARAM_IFC;
  201. pReq->Cmd = pIPMIMsgReq->Cmd;
  202. pReq->NetFnLUN = pIPMIMsgReq->NetFnLUN;
  203. if(pReq->Channel == PRIMARY_IPMB_CHANNEL)
  204. pReq->SrcQ = gFd_PrimaryIpmbResQ;
  205. else
  206. pReq->SrcQ = gFd_SecondaryIpmbResQ;
  207. /* Post the message to message handler Task */
  208. PostMsg (gFd_MsgHndlrIfc, pReq);
  209. if(pReq->ResTimeOut < 1) pReq->ResTimeOut = 10;
  210. do
  211. {
  212. if(pReq->Channel == PRIMARY_IPMB_CHANNEL)
  213. RetVal = GetMsg (gFd_PrimaryIpmbResQ, &ResPkt, pReq->ResTimeOut);
  214. else
  215. RetVal = GetMsg (gFd_SecondaryIpmbResQ, &ResPkt, pReq->ResTimeOut);
  216. }while(!RetVal && !IsResponseMatch(pReq, &ResPkt) );
  217. if (0 != RetVal)
  218. {
  219. printf("Warning: Process IPMB request fail, return timeout.\r\n");
  220. ResPkt.Param = PARAM_NORMAL_RESPONSE;
  221. ResPkt.Size = sizeof(IPMIMsgHdr_T)+2;
  222. SwapIPMIMsgHdr(((IPMIMsgHdr_T*)pReq->Data), ((IPMIMsgHdr_T*)ResPkt.Data));
  223. ResPkt.Data[sizeof(IPMIMsgHdr_T)] = CC_TIMEOUT;
  224. ResPkt.Data[sizeof(IPMIMsgHdr_T)+1] = CalculateCheckSum2(ResPkt.Data, sizeof(IPMIMsgHdr_T)+1);
  225. }
  226. /* If its not normal IPMI Response just return */
  227. if (PARAM_NO_RESPONSE == ResPkt.Param)
  228. {
  229. printf ("IPMBIfc.c : IPMB request packet dropped, not processed\n");
  230. return;
  231. }
  232. /* Send the response */
  233. if(pReq->Channel == PRIMARY_IPMB_CHANNEL)
  234. {
  235. RetVal = stm32_i2c_master_write(gFd_Primary, ResPkt.Data[0], &ResPkt.Data[1], ResPkt.Size);
  236. }
  237. else if(pReq->Channel == SECONDARY_IPMB_CHANNEL)
  238. {
  239. RetVal = stm32_i2c_master_write(gFd_Secondary, ResPkt.Data[0], &ResPkt.Data[1], ResPkt.Size);
  240. }
  241. else
  242. {
  243. printf("IPMBIfc.c: IPMB channel error. %#x\r\n", pReq->Channel);
  244. }
  245. if (0 != RetVal)
  246. {
  247. printf ("IPMBIfc.c : Unable to send a IPMI Response\n");
  248. }
  249. return;
  250. }
  251. /**
  252. * @brief Validate IPMB Checksums.
  253. * @param Data - Buffer to be validated.
  254. * @param Size - Size of the buffer.
  255. * @return TRUE if valid, FALSE if error.
  256. **/
  257. static uint8_t ValidateIPMBChkSums ( uint8_t* Data, uint8_t Size)
  258. {
  259. uint8_t i;
  260. uint8_t chksum;
  261. /* Check IPMB message min size */
  262. if (Size < MIN_IPMB_MSG_LENGTH)
  263. {
  264. printf("IPMBIfc.c: Invalid IPMB Message Length\r\n");
  265. return FALSE;
  266. }
  267. /* Validate the checksum1 */
  268. chksum = 0;
  269. for (i = 0; i < 3; i++)
  270. {
  271. chksum += *(Data + i);
  272. }
  273. if (chksum != 0)
  274. {
  275. printf ("IPMBIfc.c: Invalid checksum 1, size = %d\n",Size);
  276. for(i = 0; i < Size;i++)
  277. printf("%x ",Data[i]);
  278. printf("\n");
  279. return FALSE;
  280. }
  281. /* Validate the checksum2 */
  282. chksum = 0;
  283. for (i = 3; i < Size; i++)
  284. {
  285. chksum += *(Data + i);
  286. }
  287. if (chksum != 0)
  288. {
  289. printf("IPMBIfc.c: Invalid checksum 2, size = %d\n",Size);
  290. for(i = 0; i < Size;i++)
  291. printf("%x ",Data[i]);
  292. printf("\n");
  293. return FALSE;
  294. }
  295. return TRUE;
  296. }
  297. /*-----------------------------------------------------
  298. * @fn IsResponseMatch
  299. * @brief Checks if the Response Message corresponds to
  300. * the Request Message
  301. *
  302. * @param pReq : IPMI Request Message Packet
  303. * @param pRes : IPMI Response Message Packet
  304. *
  305. * @return 1 if match
  306. * 0 if mismatch
  307. *----------------------------------------------------*/
  308. uint8_t IsResponseMatch (MsgPkt_T* pReq, MsgPkt_T* pRes)
  309. {
  310. if( ( ((((IPMIMsgHdr_T*)pRes->Data)->RqSeqLUN) >> 2) != ((((IPMIMsgHdr_T*)pReq->Data)->RqSeqLUN) >> 2) ) &&
  311. ( (pReq->NetFnLUN & 0x4) && (PARAM_NO_RESPONSE != pRes->Param) ) )
  312. {
  313. return FALSE;
  314. }
  315. return TRUE;
  316. }
  317. /**
  318. * @fn RecvIPMBPkt
  319. * @brief This function receives IPMB request packet and post the message to
  320. * IPMB interface queue
  321. **/
  322. static void* RecvIPMBPkt (void *Param)
  323. {
  324. MsgPkt_T IPMBReqPkt;
  325. int IPMBSlaveFd;
  326. int retval;
  327. uint8_t ipmbSelect = *(uint8_t*)Param;
  328. prctl(PR_SET_NAME, __FUNCTION__, 0, 0, 0);
  329. int curThreadIndex = 0;
  330. memset(&IPMBReqPkt,0,sizeof(MsgPkt_T));
  331. if(0 == ipmbSelect)
  332. {
  333. printf ("Primary IPMB Receiver Started...\n");
  334. IPMBReqPkt.Data [0] = g_BMCInfo.IpmiConfig.PrimaryIPMBAddr;
  335. IPMBReqPkt.Channel = PRIMARY_IPMB_CHANNEL;
  336. IPMBSlaveFd = gFd_Primary;
  337. }
  338. else if(1 == ipmbSelect)
  339. {
  340. printf ("Secondary IPMB Receiver Started...\n");
  341. IPMBReqPkt.Data [0] = g_BMCInfo.IpmiConfig.SecondaryIPMBAddr;
  342. IPMBReqPkt.Channel = SECONDARY_IPMB_CHANNEL;
  343. IPMBSlaveFd = gFd_Secondary;
  344. }
  345. /* Loop forever */
  346. while (1)
  347. {
  348. retval = stm32_i2c_slave_recv(IPMBSlaveFd, &IPMBReqPkt.Data[1]);
  349. if( retval > 5)
  350. {
  351. IPMBReqPkt.Param = PARAM_REQUEST;
  352. IPMBReqPkt.Size = retval + 1; /* +1 to include BMC Slave address */
  353. /* Post the IPMB Request message to IPMBIfc Queue */
  354. if(ipmbSelect == 0)
  355. {
  356. if (0 != PostMsg (gFd_PrimaryIpmbIfcQ, &IPMBReqPkt))
  357. {
  358. printf ("IPMBIfc.c : Error posting message to IPMBIfc_Q\n");
  359. }
  360. }
  361. else
  362. {
  363. if (0 != PostMsg (gFd_SecondaryIpmbIfcQ, &IPMBReqPkt))
  364. {
  365. printf ("IPMBIfc.c : Error posting message to IPMBIfc_Q\n");
  366. }
  367. }
  368. }
  369. int cnt;
  370. if(0 == ipmbSelect)
  371. printf("---> Primary IPMB Recv: ");
  372. else
  373. printf("---> Secondary IPMB Recv: ");
  374. for(cnt=0;cnt < IPMBReqPkt.Size; cnt++)
  375. printf("%#x ", IPMBReqPkt.Data[cnt]);
  376. printf("\n");
  377. }
  378. return (void*)-1;
  379. }