blob: d1b275ebe4e5d48fa646785a1b228fbd2708cd93 [file] [log] [blame]
AppaRao Puli071f3f22018-05-24 16:45:30 +05301/*
2// Copyright (c) 2018 Intel Corporation
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15*/
16
17#include "channelcommands.hpp"
18
19#include "apphandler.hpp"
20#include "channel_layer.hpp"
21
22#include <phosphor-logging/log.hpp>
23#include <regex>
24
25using namespace phosphor::logging;
26
27namespace ipmi
28{
29
Richard Marian Thomaiyar48e55582018-12-20 15:58:04 +053030/** @struct SetChannelAccessReq
Richard Marian Thomaiyar6e1ba9e2018-11-29 06:29:21 +053031 *
32 * Structure for set channel access request command (refer spec sec 22.22)
33 */
Richard Marian Thomaiyar48e55582018-12-20 15:58:04 +053034struct SetChannelAccessReq
AppaRao Puli071f3f22018-05-24 16:45:30 +053035{
36#if BYTE_ORDER == LITTLE_ENDIAN
37 uint8_t chNum : 4;
38 uint8_t reserved_1 : 4;
39 uint8_t accessMode : 3;
40 uint8_t usrAuthDisabled : 1;
41 uint8_t msgAuthDisabled : 1;
42 uint8_t alertDisabled : 1;
43 uint8_t accessSetMode : 2;
44 uint8_t privLimit : 4;
45 uint8_t reserved_2 : 2;
46 uint8_t privSetMode : 2;
47#endif
48#if BYTE_ORDER == BIG_ENDIAN
49 uint8_t reserved_1 : 4;
50 uint8_t chNum : 4;
51 uint8_t accessSetMode : 2;
52 uint8_t alertDisabled : 1;
53 uint8_t msgAuthDisabled : 1;
54 uint8_t usrAuthDisabled : 1;
55 uint8_t accessMode : 3;
56 uint8_t privSetMode : 2;
57 uint8_t reserved_2 : 2;
58 uint8_t privLimit : 4;
59#endif
60
61} __attribute__((packed));
62
Richard Marian Thomaiyar48e55582018-12-20 15:58:04 +053063/** @struct GetChannelAccessReq
Richard Marian Thomaiyar6e1ba9e2018-11-29 06:29:21 +053064 *
65 * Structure for get channel access request command (refer spec sec 22.23)
66 */
Richard Marian Thomaiyar48e55582018-12-20 15:58:04 +053067struct GetChannelAccessReq
AppaRao Puli071f3f22018-05-24 16:45:30 +053068{
69#if BYTE_ORDER == LITTLE_ENDIAN
70 uint8_t chNum : 4;
71 uint8_t reserved_1 : 4;
72 uint8_t reserved_2 : 6;
73 uint8_t accessSetMode : 2;
74#endif
75#if BYTE_ORDER == BIG_ENDIAN
76 uint8_t reserved_1 : 4;
77 uint8_t chNum : 4;
78 uint8_t accessSetMode : 2;
79 uint8_t reserved_2 : 6;
80#endif
81} __attribute__((packed));
82
Richard Marian Thomaiyar48e55582018-12-20 15:58:04 +053083/** @struct GetChannelAccessResp
Richard Marian Thomaiyar6e1ba9e2018-11-29 06:29:21 +053084 *
85 * Structure for get channel access response command (refer spec sec 22.23)
86 */
Richard Marian Thomaiyar48e55582018-12-20 15:58:04 +053087struct GetChannelAccessResp
AppaRao Puli071f3f22018-05-24 16:45:30 +053088{
89#if BYTE_ORDER == LITTLE_ENDIAN
90 uint8_t accessMode : 3;
91 uint8_t usrAuthDisabled : 1;
92 uint8_t msgAuthDisabled : 1;
93 uint8_t alertDisabled : 1;
94 uint8_t reserved_1 : 2;
95 uint8_t privLimit : 4;
96 uint8_t reserved_2 : 4;
97#endif
98#if BYTE_ORDER == BIG_ENDIAN
99 uint8_t reserved_1 : 2;
100 uint8_t alertDisabled : 1;
101 uint8_t msgAuthDisabled : 1;
102 uint8_t usrAuthDisabled : 1;
103 uint8_t accessMode : 3;
104 uint8_t reserved_2 : 4;
105 uint8_t privLimit : 4;
106#endif
107} __attribute__((packed));
108
Richard Marian Thomaiyar48e55582018-12-20 15:58:04 +0530109/** @struct GetChannelInfoReq
Richard Marian Thomaiyar6e1ba9e2018-11-29 06:29:21 +0530110 *
111 * Structure for get channel info request command (refer spec sec 22.24)
112 */
Richard Marian Thomaiyar48e55582018-12-20 15:58:04 +0530113struct GetChannelInfoReq
AppaRao Puli071f3f22018-05-24 16:45:30 +0530114{
115#if BYTE_ORDER == LITTLE_ENDIAN
116 uint8_t chNum : 4;
117 uint8_t reserved_1 : 4;
118#endif
119#if BYTE_ORDER == BIG_ENDIAN
120 uint8_t reserved_1 : 4;
121 uint8_t chNum : 4;
122#endif
123} __attribute__((packed));
124
Richard Marian Thomaiyar48e55582018-12-20 15:58:04 +0530125/** @struct GetChannelInfoResp
Richard Marian Thomaiyar6e1ba9e2018-11-29 06:29:21 +0530126 *
127 * Structure for get channel info response command (refer spec sec 22.24)
128 */
Richard Marian Thomaiyar48e55582018-12-20 15:58:04 +0530129struct GetChannelInfoResp
AppaRao Puli071f3f22018-05-24 16:45:30 +0530130{
131#if BYTE_ORDER == LITTLE_ENDIAN
132 uint8_t chNum : 4;
133 uint8_t reserved_1 : 4;
134 uint8_t mediumType : 7;
135 uint8_t reserved_2 : 1;
136 uint8_t msgProtType : 5;
137 uint8_t reserved_3 : 3;
138 uint8_t actSessCount : 6;
139 uint8_t sessType : 2;
140#endif
141#if BYTE_ORDER == BIG_ENDIAN
142 uint8_t reserved_1 : 4;
143 uint8_t chNum : 4;
144 uint8_t reserved_2 : 1;
145 uint8_t mediumType : 7;
146 uint8_t reserved_3 : 3;
147 uint8_t msgProtType : 5;
148 uint8_t sessType : 2;
149 uint8_t actSessCount : 6;
150#endif
151 uint8_t vendorId[3];
152 uint8_t auxChInfo[2];
153} __attribute__((packed));
154
Saravanan Palanisamyb5a0f162019-03-04 18:34:44 +0530155/** @struct GetChannelPayloadSupportReq
156 *
157 * Structure for get channel payload support command request (refer spec
158 * sec 24.8)
159 */
160struct GetChannelPayloadSupportReq
161{
162#if BYTE_ORDER == LITTLE_ENDIAN
163 uint8_t chNum : 4;
164 uint8_t reserved : 4;
165#endif
166#if BYTE_ORDER == BIG_ENDIAN
167 uint8_t reserved : 4;
168 uint8_t chNum : 4;
169#endif
170} __attribute__((packed));
171
172/** @struct GetChannelPayloadSupportResp
173 *
174 * Structure for get channel payload support command response (refer spec
175 * sec 24.8)
176 */
177struct GetChannelPayloadSupportResp
178{
179 uint8_t stdPayloadType[2];
180 uint8_t sessSetupPayloadType[2];
181 uint8_t OEMPayloadType[2];
182 uint8_t reserved[2];
183} __attribute__((packed));
184
AppaRao Puli071f3f22018-05-24 16:45:30 +0530185ipmi_ret_t ipmiSetChannelAccess(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
186 ipmi_request_t request,
187 ipmi_response_t response,
188 ipmi_data_len_t data_len,
189 ipmi_context_t context)
190{
Richard Marian Thomaiyar48e55582018-12-20 15:58:04 +0530191 const SetChannelAccessReq* req = static_cast<SetChannelAccessReq*>(request);
AppaRao Puli071f3f22018-05-24 16:45:30 +0530192 size_t reqLength = *data_len;
193
194 *data_len = 0;
195
196 if (reqLength != sizeof(*req))
197 {
198 log<level::DEBUG>("Set channel access - Invalid Length");
199 return IPMI_CC_REQ_DATA_LEN_INVALID;
200 }
201
Richard Marian Thomaiyarf1d0e232018-12-08 17:36:20 +0530202 uint8_t chNum = convertCurrentChannelNum(req->chNum);
Richard Marian Thomaiyaref024012019-01-29 11:06:39 +0530203 if (!isValidChannel(chNum) || req->reserved_1 != 0 || req->reserved_2 != 0)
AppaRao Puli071f3f22018-05-24 16:45:30 +0530204 {
Richard Marian Thomaiyaref024012019-01-29 11:06:39 +0530205 log<level::DEBUG>("Set channel access - Invalid field in request");
AppaRao Puli071f3f22018-05-24 16:45:30 +0530206 return IPMI_CC_INVALID_FIELD_REQUEST;
207 }
208
209 if (EChannelSessSupported::none == getChannelSessionSupport(chNum))
210 {
211 log<level::DEBUG>("Set channel access - No support on channel");
212 return IPMI_CC_ACTION_NOT_SUPPORTED_FOR_CHANNEL;
213 }
214
215 ChannelAccess chActData;
216 ChannelAccess chNVData;
217 uint8_t setActFlag = 0;
218 uint8_t setNVFlag = 0;
219 ipmi_ret_t compCode = IPMI_CC_OK;
220
221 switch (req->accessSetMode)
222 {
223 case doNotSet:
224 // Do nothing
225 break;
226 case nvData:
227 chNVData.accessMode = req->accessMode;
228 chNVData.userAuthDisabled = req->usrAuthDisabled;
229 chNVData.perMsgAuthDisabled = req->msgAuthDisabled;
230 chNVData.alertingDisabled = req->alertDisabled;
231 setNVFlag |= (setAccessMode | setUserAuthEnabled |
232 setMsgAuthEnabled | setAlertingEnabled);
233 break;
234 case activeData:
235 chActData.accessMode = req->accessMode;
236 chActData.userAuthDisabled = req->usrAuthDisabled;
237 chActData.perMsgAuthDisabled = req->msgAuthDisabled;
238 chActData.alertingDisabled = req->alertDisabled;
239 setActFlag |= (setAccessMode | setUserAuthEnabled |
240 setMsgAuthEnabled | setAlertingEnabled);
241 break;
242 case reserved:
243 default:
244 log<level::DEBUG>("Set channel access - Invalid access set mode");
245 return IPMI_CC_INVALID_FIELD_REQUEST;
246 }
247
248 switch (req->privSetMode)
249 {
250 case doNotSet:
251 // Do nothing
252 break;
253 case nvData:
254 chNVData.privLimit = req->privLimit;
255 setNVFlag |= setPrivLimit;
256 break;
257 case activeData:
258 chActData.privLimit = req->privLimit;
259 setActFlag |= setPrivLimit;
260 break;
261 case reserved:
262 default:
263 log<level::DEBUG>("Set channel access - Invalid access priv mode");
264 return IPMI_CC_INVALID_FIELD_REQUEST;
265 }
266
267 if (setNVFlag != 0)
268 {
269 compCode = setChannelAccessPersistData(chNum, chNVData, setNVFlag);
270 if (compCode != IPMI_CC_OK)
271 {
272 log<level::DEBUG>("Set channel access - Failed to set access data");
273 return compCode;
274 }
275 }
276
277 if (setActFlag != 0)
278 {
279 compCode = setChannelAccessData(chNum, chActData, setActFlag);
280 if (compCode != IPMI_CC_OK)
281 {
282 log<level::DEBUG>("Set channel access - Failed to set access data");
283 return compCode;
284 }
285 }
286
287 return IPMI_CC_OK;
288}
289
290ipmi_ret_t ipmiGetChannelAccess(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
291 ipmi_request_t request,
292 ipmi_response_t response,
293 ipmi_data_len_t data_len,
294 ipmi_context_t context)
295{
Richard Marian Thomaiyar48e55582018-12-20 15:58:04 +0530296 const GetChannelAccessReq* req = static_cast<GetChannelAccessReq*>(request);
AppaRao Puli071f3f22018-05-24 16:45:30 +0530297 size_t reqLength = *data_len;
298
299 *data_len = 0;
300
301 if (reqLength != sizeof(*req))
302 {
303 log<level::DEBUG>("Get channel access - Invalid Length");
304 return IPMI_CC_REQ_DATA_LEN_INVALID;
305 }
306
Richard Marian Thomaiyarf1d0e232018-12-08 17:36:20 +0530307 uint8_t chNum = convertCurrentChannelNum(req->chNum);
Richard Marian Thomaiyaref024012019-01-29 11:06:39 +0530308 if (!isValidChannel(chNum) || req->reserved_1 != 0 || req->reserved_2 != 0)
AppaRao Puli071f3f22018-05-24 16:45:30 +0530309 {
Richard Marian Thomaiyaref024012019-01-29 11:06:39 +0530310 log<level::DEBUG>("Get channel access - Invalid field in request");
AppaRao Puli071f3f22018-05-24 16:45:30 +0530311 return IPMI_CC_INVALID_FIELD_REQUEST;
312 }
313
314 if ((req->accessSetMode == doNotSet) || (req->accessSetMode == reserved))
315 {
316 log<level::DEBUG>("Get channel access - Invalid Access mode");
317 return IPMI_CC_INVALID_FIELD_REQUEST;
318 }
319
320 if (EChannelSessSupported::none == getChannelSessionSupport(chNum))
321 {
322 log<level::DEBUG>("Get channel access - No support on channel");
323 return IPMI_CC_ACTION_NOT_SUPPORTED_FOR_CHANNEL;
324 }
325
Richard Marian Thomaiyar48e55582018-12-20 15:58:04 +0530326 GetChannelAccessResp* resp = static_cast<GetChannelAccessResp*>(response);
AppaRao Puli071f3f22018-05-24 16:45:30 +0530327
328 std::fill(reinterpret_cast<uint8_t*>(resp),
329 reinterpret_cast<uint8_t*>(resp) + sizeof(*resp), 0);
330
331 ChannelAccess chAccess;
332 ipmi_ret_t compCode = IPMI_CC_OK;
333
334 if (req->accessSetMode == nvData)
335 {
336 compCode = getChannelAccessPersistData(chNum, chAccess);
337 }
338 else if (req->accessSetMode == activeData)
339 {
340 compCode = getChannelAccessData(chNum, chAccess);
341 }
342
343 if (compCode != IPMI_CC_OK)
344 {
345 return compCode;
346 }
347
348 resp->accessMode = chAccess.accessMode;
349 resp->usrAuthDisabled = chAccess.userAuthDisabled;
350 resp->msgAuthDisabled = chAccess.perMsgAuthDisabled;
351 resp->alertDisabled = chAccess.alertingDisabled;
352 resp->privLimit = chAccess.privLimit;
353
354 *data_len = sizeof(*resp);
355 return IPMI_CC_OK;
356}
357
358ipmi_ret_t ipmiGetChannelInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
359 ipmi_request_t request, ipmi_response_t response,
360 ipmi_data_len_t data_len, ipmi_context_t context)
361{
Richard Marian Thomaiyar48e55582018-12-20 15:58:04 +0530362 const GetChannelInfoReq* req = static_cast<GetChannelInfoReq*>(request);
AppaRao Puli071f3f22018-05-24 16:45:30 +0530363 size_t reqLength = *data_len;
364
365 *data_len = 0;
366
367 if (reqLength != sizeof(*req))
368 {
369 log<level::DEBUG>("Get channel info - Invalid Length");
370 return IPMI_CC_REQ_DATA_LEN_INVALID;
371 }
372
Richard Marian Thomaiyarf1d0e232018-12-08 17:36:20 +0530373 uint8_t chNum = convertCurrentChannelNum(req->chNum);
Richard Marian Thomaiyaref024012019-01-29 11:06:39 +0530374 if (!isValidChannel(chNum) || req->reserved_1 != 0)
AppaRao Puli071f3f22018-05-24 16:45:30 +0530375 {
Richard Marian Thomaiyaref024012019-01-29 11:06:39 +0530376 log<level::DEBUG>("Get channel info - Invalid field in request");
AppaRao Puli071f3f22018-05-24 16:45:30 +0530377 return IPMI_CC_INVALID_FIELD_REQUEST;
378 }
379
380 // Check the existance of device for session-less channels.
381 if ((EChannelSessSupported::none != getChannelSessionSupport(chNum)) &&
382 (!(doesDeviceExist(chNum))))
383 {
384 log<level::DEBUG>("Get channel info - Device not exist");
385 return IPMI_CC_PARM_OUT_OF_RANGE;
386 }
387
Richard Marian Thomaiyar48e55582018-12-20 15:58:04 +0530388 GetChannelInfoResp* resp = static_cast<GetChannelInfoResp*>(response);
AppaRao Puli071f3f22018-05-24 16:45:30 +0530389
390 std::fill(reinterpret_cast<uint8_t*>(resp),
391 reinterpret_cast<uint8_t*>(resp) + sizeof(*resp), 0);
392
393 ChannelInfo chInfo;
394 ipmi_ret_t compCode = getChannelInfo(chNum, chInfo);
395 if (compCode != IPMI_CC_OK)
396 {
397 return compCode;
398 }
399
400 resp->chNum = chNum;
401 resp->mediumType = chInfo.mediumType;
402 resp->msgProtType = chInfo.protocolType;
403 resp->actSessCount = getChannelActiveSessions(chNum);
404 resp->sessType = chInfo.sessionSupported;
405
406 // IPMI Spec: The IPMI Enterprise Number is: 7154 (decimal)
407 resp->vendorId[0] = 0xF2;
408 resp->vendorId[1] = 0x1B;
409 resp->vendorId[2] = 0x00;
410
411 // Auxiliary Channel info - byte 1:2
412 // TODO: For System Interface(0xF) and OEM channel types, this needs
413 // to be changed acoordingly.
414 // All other channel types, its reverved
415 resp->auxChInfo[0] = 0x00;
416 resp->auxChInfo[1] = 0x00;
417
418 *data_len = sizeof(*resp);
419
420 return IPMI_CC_OK;
421}
422
Saravanan Palanisamyb5a0f162019-03-04 18:34:44 +0530423ipmi_ret_t ipmiGetChannelPayloadSupport(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
424 ipmi_request_t request,
425 ipmi_response_t response,
426 ipmi_data_len_t data_len,
427 ipmi_context_t context)
428{
429 const auto req = static_cast<GetChannelPayloadSupportReq*>(request);
430 size_t reqLength = *data_len;
431
432 *data_len = 0;
433
434 if (reqLength != sizeof(*req))
435 {
436 log<level::DEBUG>("Get channel payload - Invalid Length");
437 return IPMI_CC_REQ_DATA_LEN_INVALID;
438 }
439
440 uint8_t chNum = convertCurrentChannelNum(req->chNum);
441 if (!isValidChannel(chNum) || req->reserved != 0)
442 {
443 log<level::DEBUG>("Get channel payload - Invalid field in request");
444 return IPMI_CC_INVALID_FIELD_REQUEST;
445 }
446
447 // Not supported on sessionless channels.
448 if (EChannelSessSupported::none == getChannelSessionSupport(chNum))
449 {
450 log<level::DEBUG>("Get channel payload - Sessionless Channel");
451 return IPMI_CC_INVALID_FIELD_REQUEST;
452 }
453
454 // Session support is available in active LAN channels.
455 if ((EChannelSessSupported::none != getChannelSessionSupport(chNum)) &&
456 (!(doesDeviceExist(chNum))))
457 {
458 log<level::DEBUG>("Get channel payload - Device not exist");
459 return IPMI_CC_INVALID_FIELD_REQUEST;
460 }
461
462 auto resp = static_cast<GetChannelPayloadSupportResp*>(response);
463
464 std::fill(reinterpret_cast<uint8_t*>(resp),
465 reinterpret_cast<uint8_t*>(resp) + sizeof(*resp), 0);
466
467 // TODO: Hard coding for now.
468 // Mapping PayloadTypes to 'GetChannelPayloadSupportResp' fields:
469 // --------------------------------------------------------------
470 // Mask all except least 3 significant bits to get a value in the range of
471 // 0-7. This value maps to the bit position of given payload type in 'resp'
472 // fields.
473
474 static constexpr uint8_t payloadByteMask = 0x07;
475 static constexpr uint8_t stdPayloadTypeIPMI =
476 1 << (static_cast<uint8_t>(PayloadType::IPMI) & payloadByteMask);
477 static constexpr uint8_t stdPayloadTypeSOL =
478 1 << (static_cast<uint8_t>(PayloadType::SOL) & payloadByteMask);
479
480 static constexpr uint8_t sessPayloadTypeOpenReq =
481 1 << (static_cast<uint8_t>(PayloadType::OPEN_SESSION_REQUEST) &
482 payloadByteMask);
483 static constexpr uint8_t sessPayloadTypeRAKP1 =
484 1 << (static_cast<uint8_t>(PayloadType::RAKP1) & payloadByteMask);
485 static constexpr uint8_t sessPayloadTypeRAKP3 =
486 1 << (static_cast<uint8_t>(PayloadType::RAKP3) & payloadByteMask);
487
488 resp->stdPayloadType[0] = stdPayloadTypeIPMI | stdPayloadTypeSOL;
489 // RMCP+ Open Session request, RAKP Message1 and RAKP Message3.
490 resp->sessSetupPayloadType[0] =
491 sessPayloadTypeOpenReq | sessPayloadTypeRAKP1 | sessPayloadTypeRAKP3;
492
493 *data_len = sizeof(*resp);
494
495 return IPMI_CC_OK;
496}
497
William A. Kennington III343d0612018-12-10 15:56:24 -0800498void registerChannelFunctions() __attribute__((constructor));
AppaRao Puli071f3f22018-05-24 16:45:30 +0530499void registerChannelFunctions()
500{
501 ipmiChannelInit();
502
503 ipmi_register_callback(NETFUN_APP, IPMI_CMD_SET_CHANNEL_ACCESS, NULL,
504 ipmiSetChannelAccess, PRIVILEGE_ADMIN);
505
506 ipmi_register_callback(NETFUN_APP, IPMI_CMD_GET_CHANNEL_ACCESS, NULL,
507 ipmiGetChannelAccess, PRIVILEGE_USER);
508
509 ipmi_register_callback(NETFUN_APP, IPMI_CMD_GET_CHANNEL_INFO, NULL,
510 ipmiGetChannelInfo, PRIVILEGE_USER);
Saravanan Palanisamyb5a0f162019-03-04 18:34:44 +0530511
512 ipmi_register_callback(NETFUN_APP, IPMI_CMD_GET_CHANNEL_PAYLOAD_SUPPORT,
513 NULL, ipmiGetChannelPayloadSupport, PRIVILEGE_USER);
514
AppaRao Puli071f3f22018-05-24 16:45:30 +0530515 return;
516}
517
518} // namespace ipmi