blob: fd46837d0407810cfc7408e674f276a14ce03142 [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
155ipmi_ret_t ipmiSetChannelAccess(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
156 ipmi_request_t request,
157 ipmi_response_t response,
158 ipmi_data_len_t data_len,
159 ipmi_context_t context)
160{
Richard Marian Thomaiyar48e55582018-12-20 15:58:04 +0530161 const SetChannelAccessReq* req = static_cast<SetChannelAccessReq*>(request);
AppaRao Puli071f3f22018-05-24 16:45:30 +0530162 size_t reqLength = *data_len;
163
164 *data_len = 0;
165
166 if (reqLength != sizeof(*req))
167 {
168 log<level::DEBUG>("Set channel access - Invalid Length");
169 return IPMI_CC_REQ_DATA_LEN_INVALID;
170 }
171
Richard Marian Thomaiyarf1d0e232018-12-08 17:36:20 +0530172 uint8_t chNum = convertCurrentChannelNum(req->chNum);
AppaRao Puli071f3f22018-05-24 16:45:30 +0530173 if (!isValidChannel(chNum))
174 {
175 log<level::DEBUG>("Set channel access - Parameter out of range");
176 return IPMI_CC_INVALID_FIELD_REQUEST;
177 }
178
179 if (EChannelSessSupported::none == getChannelSessionSupport(chNum))
180 {
181 log<level::DEBUG>("Set channel access - No support on channel");
182 return IPMI_CC_ACTION_NOT_SUPPORTED_FOR_CHANNEL;
183 }
184
185 ChannelAccess chActData;
186 ChannelAccess chNVData;
187 uint8_t setActFlag = 0;
188 uint8_t setNVFlag = 0;
189 ipmi_ret_t compCode = IPMI_CC_OK;
190
191 switch (req->accessSetMode)
192 {
193 case doNotSet:
194 // Do nothing
195 break;
196 case nvData:
197 chNVData.accessMode = req->accessMode;
198 chNVData.userAuthDisabled = req->usrAuthDisabled;
199 chNVData.perMsgAuthDisabled = req->msgAuthDisabled;
200 chNVData.alertingDisabled = req->alertDisabled;
201 setNVFlag |= (setAccessMode | setUserAuthEnabled |
202 setMsgAuthEnabled | setAlertingEnabled);
203 break;
204 case activeData:
205 chActData.accessMode = req->accessMode;
206 chActData.userAuthDisabled = req->usrAuthDisabled;
207 chActData.perMsgAuthDisabled = req->msgAuthDisabled;
208 chActData.alertingDisabled = req->alertDisabled;
209 setActFlag |= (setAccessMode | setUserAuthEnabled |
210 setMsgAuthEnabled | setAlertingEnabled);
211 break;
212 case reserved:
213 default:
214 log<level::DEBUG>("Set channel access - Invalid access set mode");
215 return IPMI_CC_INVALID_FIELD_REQUEST;
216 }
217
218 switch (req->privSetMode)
219 {
220 case doNotSet:
221 // Do nothing
222 break;
223 case nvData:
224 chNVData.privLimit = req->privLimit;
225 setNVFlag |= setPrivLimit;
226 break;
227 case activeData:
228 chActData.privLimit = req->privLimit;
229 setActFlag |= setPrivLimit;
230 break;
231 case reserved:
232 default:
233 log<level::DEBUG>("Set channel access - Invalid access priv mode");
234 return IPMI_CC_INVALID_FIELD_REQUEST;
235 }
236
237 if (setNVFlag != 0)
238 {
239 compCode = setChannelAccessPersistData(chNum, chNVData, setNVFlag);
240 if (compCode != IPMI_CC_OK)
241 {
242 log<level::DEBUG>("Set channel access - Failed to set access data");
243 return compCode;
244 }
245 }
246
247 if (setActFlag != 0)
248 {
249 compCode = setChannelAccessData(chNum, chActData, setActFlag);
250 if (compCode != IPMI_CC_OK)
251 {
252 log<level::DEBUG>("Set channel access - Failed to set access data");
253 return compCode;
254 }
255 }
256
257 return IPMI_CC_OK;
258}
259
260ipmi_ret_t ipmiGetChannelAccess(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
261 ipmi_request_t request,
262 ipmi_response_t response,
263 ipmi_data_len_t data_len,
264 ipmi_context_t context)
265{
Richard Marian Thomaiyar48e55582018-12-20 15:58:04 +0530266 const GetChannelAccessReq* req = static_cast<GetChannelAccessReq*>(request);
AppaRao Puli071f3f22018-05-24 16:45:30 +0530267 size_t reqLength = *data_len;
268
269 *data_len = 0;
270
271 if (reqLength != sizeof(*req))
272 {
273 log<level::DEBUG>("Get channel access - Invalid Length");
274 return IPMI_CC_REQ_DATA_LEN_INVALID;
275 }
276
Richard Marian Thomaiyarf1d0e232018-12-08 17:36:20 +0530277 uint8_t chNum = convertCurrentChannelNum(req->chNum);
AppaRao Puli071f3f22018-05-24 16:45:30 +0530278 if (!isValidChannel(chNum))
279 {
280 log<level::DEBUG>("Get channel access - Parameter out of range");
281 return IPMI_CC_INVALID_FIELD_REQUEST;
282 }
283
284 if ((req->accessSetMode == doNotSet) || (req->accessSetMode == reserved))
285 {
286 log<level::DEBUG>("Get channel access - Invalid Access mode");
287 return IPMI_CC_INVALID_FIELD_REQUEST;
288 }
289
290 if (EChannelSessSupported::none == getChannelSessionSupport(chNum))
291 {
292 log<level::DEBUG>("Get channel access - No support on channel");
293 return IPMI_CC_ACTION_NOT_SUPPORTED_FOR_CHANNEL;
294 }
295
Richard Marian Thomaiyar48e55582018-12-20 15:58:04 +0530296 GetChannelAccessResp* resp = static_cast<GetChannelAccessResp*>(response);
AppaRao Puli071f3f22018-05-24 16:45:30 +0530297
298 std::fill(reinterpret_cast<uint8_t*>(resp),
299 reinterpret_cast<uint8_t*>(resp) + sizeof(*resp), 0);
300
301 ChannelAccess chAccess;
302 ipmi_ret_t compCode = IPMI_CC_OK;
303
304 if (req->accessSetMode == nvData)
305 {
306 compCode = getChannelAccessPersistData(chNum, chAccess);
307 }
308 else if (req->accessSetMode == activeData)
309 {
310 compCode = getChannelAccessData(chNum, chAccess);
311 }
312
313 if (compCode != IPMI_CC_OK)
314 {
315 return compCode;
316 }
317
318 resp->accessMode = chAccess.accessMode;
319 resp->usrAuthDisabled = chAccess.userAuthDisabled;
320 resp->msgAuthDisabled = chAccess.perMsgAuthDisabled;
321 resp->alertDisabled = chAccess.alertingDisabled;
322 resp->privLimit = chAccess.privLimit;
323
324 *data_len = sizeof(*resp);
325 return IPMI_CC_OK;
326}
327
328ipmi_ret_t ipmiGetChannelInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
329 ipmi_request_t request, ipmi_response_t response,
330 ipmi_data_len_t data_len, ipmi_context_t context)
331{
Richard Marian Thomaiyar48e55582018-12-20 15:58:04 +0530332 const GetChannelInfoReq* req = static_cast<GetChannelInfoReq*>(request);
AppaRao Puli071f3f22018-05-24 16:45:30 +0530333 size_t reqLength = *data_len;
334
335 *data_len = 0;
336
337 if (reqLength != sizeof(*req))
338 {
339 log<level::DEBUG>("Get channel info - Invalid Length");
340 return IPMI_CC_REQ_DATA_LEN_INVALID;
341 }
342
Richard Marian Thomaiyarf1d0e232018-12-08 17:36:20 +0530343 uint8_t chNum = convertCurrentChannelNum(req->chNum);
AppaRao Puli071f3f22018-05-24 16:45:30 +0530344 if (!isValidChannel(chNum))
345 {
346 log<level::DEBUG>("Get channel info - Parameter out of range");
347 return IPMI_CC_INVALID_FIELD_REQUEST;
348 }
349
350 // Check the existance of device for session-less channels.
351 if ((EChannelSessSupported::none != getChannelSessionSupport(chNum)) &&
352 (!(doesDeviceExist(chNum))))
353 {
354 log<level::DEBUG>("Get channel info - Device not exist");
355 return IPMI_CC_PARM_OUT_OF_RANGE;
356 }
357
Richard Marian Thomaiyar48e55582018-12-20 15:58:04 +0530358 GetChannelInfoResp* resp = static_cast<GetChannelInfoResp*>(response);
AppaRao Puli071f3f22018-05-24 16:45:30 +0530359
360 std::fill(reinterpret_cast<uint8_t*>(resp),
361 reinterpret_cast<uint8_t*>(resp) + sizeof(*resp), 0);
362
363 ChannelInfo chInfo;
364 ipmi_ret_t compCode = getChannelInfo(chNum, chInfo);
365 if (compCode != IPMI_CC_OK)
366 {
367 return compCode;
368 }
369
370 resp->chNum = chNum;
371 resp->mediumType = chInfo.mediumType;
372 resp->msgProtType = chInfo.protocolType;
373 resp->actSessCount = getChannelActiveSessions(chNum);
374 resp->sessType = chInfo.sessionSupported;
375
376 // IPMI Spec: The IPMI Enterprise Number is: 7154 (decimal)
377 resp->vendorId[0] = 0xF2;
378 resp->vendorId[1] = 0x1B;
379 resp->vendorId[2] = 0x00;
380
381 // Auxiliary Channel info - byte 1:2
382 // TODO: For System Interface(0xF) and OEM channel types, this needs
383 // to be changed acoordingly.
384 // All other channel types, its reverved
385 resp->auxChInfo[0] = 0x00;
386 resp->auxChInfo[1] = 0x00;
387
388 *data_len = sizeof(*resp);
389
390 return IPMI_CC_OK;
391}
392
William A. Kennington III343d0612018-12-10 15:56:24 -0800393void registerChannelFunctions() __attribute__((constructor));
AppaRao Puli071f3f22018-05-24 16:45:30 +0530394void registerChannelFunctions()
395{
396 ipmiChannelInit();
397
398 ipmi_register_callback(NETFUN_APP, IPMI_CMD_SET_CHANNEL_ACCESS, NULL,
399 ipmiSetChannelAccess, PRIVILEGE_ADMIN);
400
401 ipmi_register_callback(NETFUN_APP, IPMI_CMD_GET_CHANNEL_ACCESS, NULL,
402 ipmiGetChannelAccess, PRIVILEGE_USER);
403
404 ipmi_register_callback(NETFUN_APP, IPMI_CMD_GET_CHANNEL_INFO, NULL,
405 ipmiGetChannelInfo, PRIVILEGE_USER);
406 return;
407}
408
409} // namespace ipmi