]> git.zerfleddert.de Git - rsbs2/blobdiff - bmc/ipmb.c
implement all remaining IPMB queries seen on the wire
[rsbs2] / bmc / ipmb.c
index 7d272fbc994bb29f89d0196f8d2701e6c3154ae5..fa057c92925404b3de34292c098c6506a9374e97 100644 (file)
@@ -1,5 +1,8 @@
+#include <string.h>
 #include <stdio.h>
 
+#include "i2c.h"
+#include "chassis.h"
 #include "ipmb.h"
 
 uint8_t ipmb_csum(unsigned char *buf, int len)
@@ -14,43 +17,232 @@ uint8_t ipmb_csum(unsigned char *buf, int len)
        return -csum;
 }
 
-void decode_ipmb_pkt(unsigned char *buf, int len)
+void ipmb_send(struct ipmb_resp *resp, unsigned char *data, uint8_t datalen)
 {
+       unsigned char buf[24];
+       int len;
+#ifdef DEBUG
        int i;
-       struct ipmb_req req;
+#endif
 
-       req.rsSA = buf[0];
-       req.netFn = (buf[1]>>2)&0x3f;
-       req.rsLUN = (buf[1] & 0x03);
-       req.rqSA = buf[3];
-       req.rqSEQ = (buf[4]>>2)&0x3f;
-       req.rqLUN = (buf[4] & 0x03);
-       req.cmd = buf[5];
-       req.data = buf+6;
-       req.datalen = len - 6 - 1;
+       buf[0] = resp->rqSA;
+       buf[1] = ((resp->netFn)<<2) | (resp->rqLUN & 0x3);
+       buf[2] = ipmb_csum(buf, 2);
+       buf[3] = resp->rsSA;
+       buf[4] = ((resp->rqSEQ)<<2) | (resp->rsLUN & 0x3);
+       buf[5] = resp->cmd;
+       memcpy(buf+6, data, datalen);
+       len = datalen + 7;
+       buf[len-1] = ipmb_csum(buf+3, len - 4);
+
+#ifdef DEBUG
+       printf("Sending: ");
+       for(i = 0; i < len; i++) {
+               printf("0x%02x ", buf[i]);
+       }
+       printf("\n");
+#endif
+
+       i2c_send(buf, len);
+
+}
+
+#ifdef DEBUG
+void ipmb_dump_req(struct ipmb_req *req)
+{
+       int i;
 
        printf(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
        printf("Connection Header:\n");
-       printf("\trs Slave Addr.: 0x%02x\n", req.rsSA);
-       printf("\tnetFn: 0x%02x, LUN: 0x%02x\n", req.netFn, req.rsLUN);
-       printf("\tChecksum: 0x%02x (%s)\n", buf[2],
-               (buf[2] == ipmb_csum(buf, 2)) ? "OK" : "Wrong");
+       printf("\trs Slave Addr.: 0x%02x\n", req->rsSA);
+       printf("\tnetFn: 0x%02x, LUN: 0x%02x\n", req->netFn, req->rsLUN);
        printf("Data:\n");
-       printf("\trq Slave Addr.: 0x%02x\n", req.rqSA);
-       printf("\trqSeq: 0x%02x, rqLUN: 0x%02x\n", req.rqSEQ, req.rqLUN);
-       printf("\tcmd: 0x%02x\n", req.cmd);
+       printf("\trq Slave Addr.: 0x%02x\n", req->rqSA);
+       printf("\trqSeq: 0x%02x, rqLUN: 0x%02x\n", req->rqSEQ, req->rqLUN);
+       printf("\tcmd: 0x%02x\n", req->cmd);
        printf("\tData: ");
-       for(i = 0; i < req.datalen; i++) {
-               printf("0x%02x ", req.data[i]);
+       for(i = 0; i < req->datalen; i++) {
+               printf("0x%02x ", req->data[i]);
        }
        printf("\n");
-       printf("\tChecksum: 0x%02x (%s)\n", buf[len-1],
-               (buf[len-1] == ipmb_csum(buf+3, len-4)) ? "OK" : "Wrong");
        printf("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
+}
+#endif
+
+void ipmb_invalid(struct ipmb_resp *resp)
+{
+#if 1
+       static unsigned char cmd_invalid[] = {IPMB_CC_INVALID};
+
+       ipmb_send(resp, cmd_invalid, sizeof(cmd_invalid));
+#endif
+}
+
+void ipmb_cmd(struct ipmb_req *req)
+{
+       struct ipmb_resp resp;
+       static unsigned char get_devid[] =
+               {IPMB_CC_NORMALLY, 0x42, 0x42, 0x01, 0x01, 0x51, 0xff /* Add. Dev. Supp */, 0x00, 0x00, 0x00, 0x00, 0x00 };
+       static unsigned char get_wd_timer[] =
+               {IPMB_CC_NORMALLY, 0x42, 0x00, 0x00, 0x04, 0xff, 0xff, 0xfe, 0xfe};
+       static unsigned char cc_normal[] =
+               {IPMB_CC_NORMALLY};
+       static unsigned char sel_info[] =
+               {IPMB_CC_NORMALLY, 0x51, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00};
+       static unsigned char sel_alloc_info[] =
+               {IPMB_CC_NORMALLY, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+       static unsigned char sel_entry[] =
+               {IPMB_CC_ERROR};
+       static unsigned char sel_timestamp[] =
+               {IPMB_CC_NORMALLY, 0x00, 0x00, 0x00, 0x00};
+       static unsigned char chassis_status[] =
+               {IPMB_CC_NORMALLY, 0x60, 0x10, 0x00, 0x00};
+       static unsigned char reserve_sdr[] =
+               {IPMB_CC_NORMALLY, 0x00, 0x00};
+       static unsigned char get_sdr[] =
+               {IPMB_CC_NORMALLY, 0xff, 0xff};
+
+       resp.rqSA = req->rqSA;
+       resp.netFn = req->netFn+1;
+       resp.rqLUN = req->rqLUN;
+       resp.rsSA = req->rsSA;
+       resp.rqSEQ = req->rqSEQ;
+       resp.rsLUN = req->rsLUN;
+       resp.cmd = req->cmd;
+
+       switch (req->netFn) {
+               case IPMB_NETFN_CHASSIS:
+                       switch (req->cmd) {
+                               case IPMB_CHASSIS_GET_STATUS:
+                                       ipmb_send(&resp, chassis_status, sizeof(chassis_status));
+                                       break;
+                               case IPMB_CHASSIS_CONTROL:
+                                       chassis_control(*(req->data));
+                                       ipmb_send(&resp, cc_normal, sizeof(cc_normal));
+                                       break;
+                               default:
+#ifdef DEBUG
+                                       printf("Unknown chassis cmd 0x%02x\n", req->cmd);
+                                       ipmb_dump_req(req);
+#endif
+                                       ipmb_invalid(&resp);
+                                       break;
+                       }
+                       break;
+
+               case IPMB_NETFN_SENSOR_EVENT:
+                       switch (req->cmd) {
+                               case IPMB_SE_PLATFORM_EVENT:
+                                       /*
+                                        * >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+                                        * Connection Header:
+                                        *         rs Slave Addr.: 0x24
+                                        *         netFn: 0x04, LUN: 0x00
+                                        * Data:
+                                        *         rq Slave Addr.: 0x28
+                                        *         rqSeq: 0x03, rqLUN: 0x00
+                                        *         cmd: 0x02
+                                        *         Data: 0x03 0xc8 0x00 0x6f 0x61 0x8f 0x03
+                                        * <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
+                                        * data[0] - EvMRev:                            0x03
+                                        * data[1] - Sensor Type:                       0xc8
+                                        * data[2] - Sensor #:                          0x00
+                                        * data[3] - Event Dir(1)|Event Type(7):        0x6f: 0x0|0x6f (assert, discrete)
+                                        * data[4] - Event Data:                        0x61
+                                        * data[5] - Event Data:                        0x8f
+                                        * data[6] - Event Data:                        0x03
+                                        */
+                                       ipmb_send(&resp, cc_normal, sizeof(cc_normal));
+                                       break;
+
+                                       
+                               default:
+#ifdef DEBUG
+                                       printf("Unknown sensor cmd 0x%02x\n", req->cmd);
+                                       ipmb_dump_req(req);
+#endif
+                                       ipmb_invalid(&resp);
+                                       break;
+                       }
+                       break;
+
+               case IPMB_NETFN_APP:
+                       switch (req->cmd) {
+                               case IPMB_APP_GET_DEVICE_ID:
+                                       ipmb_send(&resp, get_devid, sizeof(get_devid));
+                                       break;
+
+                               case IPMB_APP_GET_WATCHDOG_TIMER:
+                                       ipmb_send(&resp, get_wd_timer, sizeof(get_wd_timer));
+                                       break;
+
+                               default:
+#ifdef DEBUG
+                                       printf("Unknown app cmd 0x%02x\n", req->cmd);
+                                       ipmb_dump_req(req);
+#endif
+                                       ipmb_invalid(&resp);
+                                       break;
+                       }
+                       break;
+
+               case IPMB_NETFN_STORAGE:
+                       switch (req->cmd) {
+                               case IPMB_STORAGE_RESERVE_SDR:
+                                       ipmb_send(&resp, reserve_sdr, sizeof(reserve_sdr));
+                                       break;
+                               case IPMB_STORAGE_GET_SDR:
+                                       ipmb_send(&resp, get_sdr, sizeof(get_sdr));
+                                       break;
+                               case IPMB_STORAGE_GET_SEL_INFO:
+                                       ipmb_send(&resp, sel_info, sizeof(sel_info));
+                                       break;
+                               case IPMB_STORAGE_GET_SEL_ALLOCATION:
+                                       ipmb_send(&resp, sel_alloc_info, sizeof(sel_alloc_info));
+                                       break;
+                               case IPMB_STORAGE_GET_SEL_ENTRY:
+                                       ipmb_send(&resp, sel_entry, sizeof(sel_entry));
+                                       break;
+                               case IPMB_STORAGE_GET_SEL_TIME:
+                                       ipmb_send(&resp, sel_timestamp, sizeof(sel_timestamp));
+                                       break;
+                               default:
+#ifdef DEBUG
+                                       printf("Unknown storage cmd 0x%02x\n", req->cmd);
+                                       ipmb_dump_req(req);
+#endif
+                                       ipmb_invalid(&resp);
+                                       break;
+                       }
+                       break;
+
+               default:
+#ifdef DEBUG
+                       printf("Unknown netFn 0x%02x\n", req->netFn);
+                       ipmb_dump_req(req);
+#endif
+                       ipmb_invalid(&resp);
+                       break;
+       }
+}
+
+void decode_ipmb_pkt(unsigned char *buf, int len)
+{
+       struct ipmb_req req;
 
        if ((buf[2] != ipmb_csum(buf, 2)) ||
-           (buf[len-1] == ipmb_csum(buf+3, len-4)))
+           (buf[len-1] != ipmb_csum(buf+3, len-4)))
                return; /* Checksum wrong */
 
-       //i2c_send((unsigned char*)"\x28\x00",1);
+       req.rsSA = buf[0];
+       req.netFn = (buf[1]>>2)&0x3f;
+       req.rsLUN = (buf[1] & 0x03);
+       req.rqSA = buf[3];
+       req.rqSEQ = (buf[4]>>2)&0x3f;
+       req.rqLUN = (buf[4] & 0x03);
+       req.cmd = buf[5];
+       req.data = buf+6;
+       req.datalen = len - 6 - 1;
+
+       ipmb_cmd(&req);
 }
Impressum, Datenschutz