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