]> git.zerfleddert.de Git - rsbs2/blame - bmc/ipmb.c
implement all remaining IPMB queries seen on the wire
[rsbs2] / bmc / ipmb.c
CommitLineData
da7751cb 1#include <string.h>
d5193055
MG
2#include <stdio.h>
3
da7751cb
MG
4#include "i2c.h"
5#include "chassis.h"
d5193055
MG
6#include "ipmb.h"
7
8uint8_t ipmb_csum(unsigned char *buf, int len)
9{
10 uint8_t csum = 0x00;
11 int i;
12
13 for(i = 0; i < len; i++) {
14 csum += buf[i];
15 }
16
17 return -csum;
18}
19
67a9a9e8 20void ipmb_send(struct ipmb_resp *resp, unsigned char *data, uint8_t datalen)
d5193055 21{
da7751cb
MG
22 unsigned char buf[24];
23 int len;
24#ifdef DEBUG
d5193055 25 int i;
da7751cb 26#endif
d5193055 27
da7751cb
MG
28 buf[0] = resp->rqSA;
29 buf[1] = ((resp->netFn)<<2) | (resp->rqLUN & 0x3);
30 buf[2] = ipmb_csum(buf, 2);
31 buf[3] = resp->rsSA;
32 buf[4] = ((resp->rqSEQ)<<2) | (resp->rsLUN & 0x3);
33 buf[5] = resp->cmd;
67a9a9e8
MG
34 memcpy(buf+6, data, datalen);
35 len = datalen + 7;
da7751cb
MG
36 buf[len-1] = ipmb_csum(buf+3, len - 4);
37
38#ifdef DEBUG
39 printf("Sending: ");
40 for(i = 0; i < len; i++) {
41 printf("0x%02x ", buf[i]);
42 }
43 printf("\n");
44#endif
45
46 i2c_send(buf, len);
47
48}
49
50#ifdef DEBUG
51void ipmb_dump_req(struct ipmb_req *req)
52{
53 int i;
d5193055
MG
54
55 printf(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
56 printf("Connection Header:\n");
da7751cb
MG
57 printf("\trs Slave Addr.: 0x%02x\n", req->rsSA);
58 printf("\tnetFn: 0x%02x, LUN: 0x%02x\n", req->netFn, req->rsLUN);
d5193055 59 printf("Data:\n");
da7751cb
MG
60 printf("\trq Slave Addr.: 0x%02x\n", req->rqSA);
61 printf("\trqSeq: 0x%02x, rqLUN: 0x%02x\n", req->rqSEQ, req->rqLUN);
62 printf("\tcmd: 0x%02x\n", req->cmd);
d5193055 63 printf("\tData: ");
da7751cb
MG
64 for(i = 0; i < req->datalen; i++) {
65 printf("0x%02x ", req->data[i]);
d5193055
MG
66 }
67 printf("\n");
d5193055 68 printf("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
da7751cb
MG
69}
70#endif
71
72void ipmb_invalid(struct ipmb_resp *resp)
73{
67a9a9e8
MG
74#if 1
75 static unsigned char cmd_invalid[] = {IPMB_CC_INVALID};
da7751cb 76
67a9a9e8 77 ipmb_send(resp, cmd_invalid, sizeof(cmd_invalid));
da7751cb
MG
78#endif
79}
80
81void ipmb_cmd(struct ipmb_req *req)
82{
83 struct ipmb_resp resp;
84 static unsigned char get_devid[] =
85 {IPMB_CC_NORMALLY, 0x42, 0x42, 0x01, 0x01, 0x51, 0xff /* Add. Dev. Supp */, 0x00, 0x00, 0x00, 0x00, 0x00 };
86 static unsigned char get_wd_timer[] =
87 {IPMB_CC_NORMALLY, 0x42, 0x00, 0x00, 0x04, 0xff, 0xff, 0xfe, 0xfe};
88 static unsigned char cc_normal[] =
89 {IPMB_CC_NORMALLY};
67a9a9e8
MG
90 static unsigned char sel_info[] =
91 {IPMB_CC_NORMALLY, 0x51, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00};
92 static unsigned char sel_alloc_info[] =
93 {IPMB_CC_NORMALLY, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
94 static unsigned char sel_entry[] =
95 {IPMB_CC_ERROR};
96 static unsigned char sel_timestamp[] =
97 {IPMB_CC_NORMALLY, 0x00, 0x00, 0x00, 0x00};
98 static unsigned char chassis_status[] =
99 {IPMB_CC_NORMALLY, 0x60, 0x10, 0x00, 0x00};
100 static unsigned char reserve_sdr[] =
101 {IPMB_CC_NORMALLY, 0x00, 0x00};
102 static unsigned char get_sdr[] =
103 {IPMB_CC_NORMALLY, 0xff, 0xff};
da7751cb
MG
104
105 resp.rqSA = req->rqSA;
106 resp.netFn = req->netFn+1;
107 resp.rqLUN = req->rqLUN;
108 resp.rsSA = req->rsSA;
109 resp.rqSEQ = req->rqSEQ;
110 resp.rsLUN = req->rsLUN;
111 resp.cmd = req->cmd;
112
113 switch (req->netFn) {
114 case IPMB_NETFN_CHASSIS:
115 switch (req->cmd) {
67a9a9e8
MG
116 case IPMB_CHASSIS_GET_STATUS:
117 ipmb_send(&resp, chassis_status, sizeof(chassis_status));
118 break;
da7751cb
MG
119 case IPMB_CHASSIS_CONTROL:
120 chassis_control(*(req->data));
67a9a9e8 121 ipmb_send(&resp, cc_normal, sizeof(cc_normal));
da7751cb
MG
122 break;
123 default:
124#ifdef DEBUG
125 printf("Unknown chassis cmd 0x%02x\n", req->cmd);
126 ipmb_dump_req(req);
127#endif
128 ipmb_invalid(&resp);
129 break;
130 }
131 break;
132
133 case IPMB_NETFN_SENSOR_EVENT:
134 switch (req->cmd) {
4f3bb118
MG
135 case IPMB_SE_PLATFORM_EVENT:
136 /*
137 * >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
138 * Connection Header:
139 * rs Slave Addr.: 0x24
140 * netFn: 0x04, LUN: 0x00
141 * Data:
142 * rq Slave Addr.: 0x28
143 * rqSeq: 0x03, rqLUN: 0x00
144 * cmd: 0x02
145 * Data: 0x03 0xc8 0x00 0x6f 0x61 0x8f 0x03
146 * <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
147 * data[0] - EvMRev: 0x03
148 * data[1] - Sensor Type: 0xc8
149 * data[2] - Sensor #: 0x00
150 * data[3] - Event Dir(1)|Event Type(7): 0x6f: 0x0|0x6f (assert, discrete)
151 * data[4] - Event Data: 0x61
152 * data[5] - Event Data: 0x8f
153 * data[6] - Event Data: 0x03
154 */
67a9a9e8 155 ipmb_send(&resp, cc_normal, sizeof(cc_normal));
4f3bb118
MG
156 break;
157
158
da7751cb
MG
159 default:
160#ifdef DEBUG
161 printf("Unknown sensor cmd 0x%02x\n", req->cmd);
162 ipmb_dump_req(req);
163#endif
164 ipmb_invalid(&resp);
165 break;
166 }
167 break;
168
169 case IPMB_NETFN_APP:
170 switch (req->cmd) {
171 case IPMB_APP_GET_DEVICE_ID:
67a9a9e8 172 ipmb_send(&resp, get_devid, sizeof(get_devid));
da7751cb
MG
173 break;
174
175 case IPMB_APP_GET_WATCHDOG_TIMER:
67a9a9e8 176 ipmb_send(&resp, get_wd_timer, sizeof(get_wd_timer));
da7751cb
MG
177 break;
178
179 default:
180#ifdef DEBUG
181 printf("Unknown app cmd 0x%02x\n", req->cmd);
182 ipmb_dump_req(req);
183#endif
184 ipmb_invalid(&resp);
185 break;
186 }
187 break;
188
189 case IPMB_NETFN_STORAGE:
190 switch (req->cmd) {
67a9a9e8
MG
191 case IPMB_STORAGE_RESERVE_SDR:
192 ipmb_send(&resp, reserve_sdr, sizeof(reserve_sdr));
193 break;
194 case IPMB_STORAGE_GET_SDR:
195 ipmb_send(&resp, get_sdr, sizeof(get_sdr));
196 break;
197 case IPMB_STORAGE_GET_SEL_INFO:
198 ipmb_send(&resp, sel_info, sizeof(sel_info));
199 break;
200 case IPMB_STORAGE_GET_SEL_ALLOCATION:
201 ipmb_send(&resp, sel_alloc_info, sizeof(sel_alloc_info));
202 break;
203 case IPMB_STORAGE_GET_SEL_ENTRY:
204 ipmb_send(&resp, sel_entry, sizeof(sel_entry));
205 break;
206 case IPMB_STORAGE_GET_SEL_TIME:
207 ipmb_send(&resp, sel_timestamp, sizeof(sel_timestamp));
208 break;
da7751cb
MG
209 default:
210#ifdef DEBUG
211 printf("Unknown storage cmd 0x%02x\n", req->cmd);
212 ipmb_dump_req(req);
213#endif
214 ipmb_invalid(&resp);
215 break;
216 }
217 break;
218
219 default:
220#ifdef DEBUG
221 printf("Unknown netFn 0x%02x\n", req->netFn);
222 ipmb_dump_req(req);
223#endif
224 ipmb_invalid(&resp);
225 break;
226 }
227}
228
229void decode_ipmb_pkt(unsigned char *buf, int len)
230{
231 struct ipmb_req req;
d5193055
MG
232
233 if ((buf[2] != ipmb_csum(buf, 2)) ||
da7751cb 234 (buf[len-1] != ipmb_csum(buf+3, len-4)))
d5193055
MG
235 return; /* Checksum wrong */
236
da7751cb
MG
237 req.rsSA = buf[0];
238 req.netFn = (buf[1]>>2)&0x3f;
239 req.rsLUN = (buf[1] & 0x03);
240 req.rqSA = buf[3];
241 req.rqSEQ = (buf[4]>>2)&0x3f;
242 req.rqLUN = (buf[4] & 0x03);
243 req.cmd = buf[5];
244 req.data = buf+6;
245 req.datalen = len - 6 - 1;
246
247 ipmb_cmd(&req);
d5193055 248}
Impressum, Datenschutz