1 /*
2 * bmc_transport.c
3 *
4 * MontaVista IPMI code for emulating a MC.
5 *
6 * Author: MontaVista Software, Inc.
7 * Corey Minyard <minyard@mvista.com>
8 * source@mvista.com
9 *
10 * Copyright 2003,2012 MontaVista Software Inc.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public License
14 * as published by the Free Software Foundation; either version 2 of
15 * the License, or (at your option) any later version.
16 *
17 *
18 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
19 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
20 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
23 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
24 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
26 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
27 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 *
29 * You should have received a copy of the GNU Lesser General Public
30 * License along with this program; if not, write to the Free
31 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
32 *
33 * Modified BSD Licence
34 *
35 * Redistribution and use in source and binary forms, with or without
36 * modification, are permitted provided that the following conditions
37 * are met:
38 *
39 * 1. Redistributions of source code must retain the above copyright
40 * notice, this list of conditions and the following disclaimer.
41 * 2. Redistributions in binary form must reproduce the above
42 * copyright notice, this list of conditions and the following
43 * disclaimer in the documentation and/or other materials provided
44 * with the distribution.
45 * 3. The name of the author may not be used to endorse or promote
46 * products derived from this software without specific prior
47 * written permission.
48 */
49
50 #include "bmc.h"
51
52 #include <errno.h>
53 #include <string.h>
54
55 #include <OpenIPMI/ipmi_err.h>
56 #include <OpenIPMI/ipmi_msgbits.h>
57
58 static void
handle_ipmi_set_lan_config_parms(lmc_data_t * mc,msg_t * msg,unsigned char * rdata,unsigned int * rdata_len,void * cb_data)59 handle_ipmi_set_lan_config_parms(lmc_data_t *mc,
60 msg_t *msg,
61 unsigned char *rdata,
62 unsigned int *rdata_len,
63 void *cb_data)
64 {
65 unsigned char lchan;
66 channel_t *chan;
67
68 if (msg->len < 3) {
69 rdata[0] = IPMI_REQUEST_DATA_LENGTH_INVALID_CC;
70 *rdata_len = 1;
71 return;
72 }
73
74 lchan = msg->data[0];
75 if (lchan == 0xe)
76 lchan = msg->channel;
77 else if (lchan >= IPMI_MAX_CHANNELS) {
78 rdata[0] = IPMI_INVALID_DATA_FIELD_CC;
79 *rdata_len = 1;
80 return;
81 }
82
83 if (!mc->channels[lchan]) {
84 rdata[0] = IPMI_NOT_PRESENT_CC;
85 *rdata_len = 1;
86 return;
87 }
88 chan = mc->channels[lchan];
89
90 if (!chan->set_lan_parms) {
91 rdata[0] = IPMI_INVALID_CMD_CC;
92 *rdata_len = 1;
93 return;
94 }
95
96 chan->set_lan_parms(chan, msg, rdata, rdata_len);
97 }
98
99 static void
handle_ipmi_get_lan_config_parms(lmc_data_t * mc,msg_t * msg,unsigned char * rdata,unsigned int * rdata_len,void * cb_data)100 handle_ipmi_get_lan_config_parms(lmc_data_t *mc,
101 msg_t *msg,
102 unsigned char *rdata,
103 unsigned int *rdata_len,
104 void *cb_data)
105 {
106 unsigned char lchan;
107 channel_t *chan;
108
109 if (msg->len < 4) {
110 rdata[0] = IPMI_REQUEST_DATA_LENGTH_INVALID_CC;
111 *rdata_len = 1;
112 return;
113 }
114
115 lchan = msg->data[0];
116 if (lchan == 0xe)
117 lchan = msg->channel;
118 else if (lchan >= IPMI_MAX_CHANNELS) {
119 rdata[0] = IPMI_INVALID_DATA_FIELD_CC;
120 *rdata_len = 1;
121 return;
122 }
123
124 if (!mc->channels[lchan]) {
125 rdata[0] = IPMI_NOT_PRESENT_CC;
126 *rdata_len = 1;
127 return;
128 }
129
130 chan = mc->channels[lchan];
131
132 if (!chan->get_lan_parms) {
133 rdata[0] = IPMI_INVALID_CMD_CC;
134 *rdata_len = 1;
135 return;
136 }
137
138 chan->get_lan_parms(chan, msg, rdata, rdata_len);
139 }
140
141 static void
handle_set_sol_config_parms(lmc_data_t * mc,msg_t * msg,unsigned char * rdata,unsigned int * rdata_len,void * cb_data)142 handle_set_sol_config_parms(lmc_data_t *mc,
143 msg_t *msg,
144 unsigned char *rdata,
145 unsigned int *rdata_len,
146 void *cb_data)
147 {
148 unsigned char err = 0;
149 unsigned char val;
150 int write_config = 0;
151 ipmi_sol_t *sol = &mc->sol;
152
153 if (!mc->sol.configured) {
154 handle_invalid_cmd(mc, rdata, rdata_len);
155 return;
156 }
157
158 if (msg->len < 3) {
159 rdata[0] = IPMI_REQUEST_DATA_LENGTH_INVALID_CC;
160 *rdata_len = 1;
161 return;
162 }
163
164 /*
165 * There is a channel in this message, but as far as I can tell,
166 * it is completely without point. The data is generic to the
167 * management controller. So just ignore it.
168 */
169
170 switch (msg->data[1]) {
171 case 0:
172 switch (msg->data[2] & 0x3) {
173 case 0:
174 if (sol->set_in_progress) {
175 /* Rollback */
176 memcpy(&mc->sol.solparm, &mc->sol.solparm_rollback,
177 sizeof(solparm_t));
178 write_config = 1;
179 }
180 break;
181
182 case 1:
183 if (sol->set_in_progress)
184 err = 0x81; /* Another user is writing. */
185 else {
186 /* Save rollback data */
187 memcpy(&mc->sol.solparm_rollback, &mc->sol.solparm,
188 sizeof(solparm_t));
189 sol->set_in_progress = 1;
190 }
191 break;
192
193 case 2:
194 sol->set_in_progress = 0;
195 break;
196
197 case 3:
198 err = IPMI_INVALID_DATA_FIELD_CC;
199 }
200 break;
201
202 case 1:
203 sol->solparm.enabled = msg->data[2] & 1;
204 write_config = 1;
205 break;
206
207 case 5:
208 val = msg->data[2] & 0xf;
209 if ((val < 6) || (val > 0xa)) {
210 err = IPMI_INVALID_DATA_FIELD_CC;
211 } else {
212 sol->solparm.bitrate_nonv = val;
213 write_config = 1;
214 }
215 break;
216
217 case 6:
218 val = msg->data[2] & 0xf;
219 if ((val < 6) || (val > 0xa)) {
220 err = IPMI_INVALID_DATA_FIELD_CC;
221 } else {
222 sol->solparm.bitrate = val;
223 if (sol->update_bitrate)
224 sol->update_bitrate(mc);
225 }
226 break;
227
228 default:
229 err = 0x80; /* Parm not supported */
230 }
231
232 if (write_config)
233 write_sol_config(mc);
234
235 rdata[0] = err;
236 *rdata_len = 1;
237 }
238
239 static void
handle_get_sol_config_parms(lmc_data_t * mc,msg_t * msg,unsigned char * rdata,unsigned int * rdata_len,void * cb_data)240 handle_get_sol_config_parms(lmc_data_t *mc,
241 msg_t *msg,
242 unsigned char *rdata,
243 unsigned int *rdata_len,
244 void *cb_data)
245 {
246 ipmi_sol_t *sol = &mc->sol;
247 unsigned char databyte = 0;
248
249 if (!mc->sol.configured) {
250 handle_invalid_cmd(mc, rdata, rdata_len);
251 return;
252 }
253
254 if (msg->len < 4) {
255 rdata[0] = IPMI_REQUEST_DATA_LENGTH_INVALID_CC;
256 *rdata_len = 1;
257 return;
258 }
259
260 /*
261 * There is a channel in this message, but as far as I can tell,
262 * it is completely without point. The data is generic to the
263 * management controller. So just ignore it.
264 */
265
266 switch (msg->data[1]) {
267 case 0:
268 databyte = sol->set_in_progress;
269 break;
270
271 case 1:
272 databyte = sol->solparm.enabled;
273 break;
274
275 case 5:
276 databyte = sol->solparm.bitrate_nonv;
277 break;
278
279 case 6:
280 databyte = sol->solparm.bitrate;
281 break;
282
283 default:
284 rdata[0] = 0x80; /* Parm not supported */
285 *rdata_len = 1;
286 return;
287 }
288
289 rdata[0] = 0;
290 rdata[1] = 0x11;
291 rdata[2] = databyte;
292 *rdata_len = 3;
293 }
294
295 cmd_handler_f transport_netfn_handlers[256] = {
296 [IPMI_SET_LAN_CONFIG_PARMS_CMD] = handle_ipmi_set_lan_config_parms,
297 [IPMI_GET_LAN_CONFIG_PARMS_CMD] = handle_ipmi_get_lan_config_parms,
298 [IPMI_SET_SOL_CONFIGURATION_PARAMETERS] = handle_set_sol_config_parms,
299 [IPMI_GET_SOL_CONFIGURATION_PARAMETERS] = handle_get_sol_config_parms
300 };
301