blob: 865d764ee7e67de2720c6f4e4e9019a0c471c473 [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 Thomaiyar6e1ba9e2018-11-29 06:29:21 +053030/** @struct setChannelAccessReq
31 *
32 * Structure for set channel access request command (refer spec sec 22.22)
33 */
AppaRao Puli071f3f22018-05-24 16:45:30 +053034struct setChannelAccessReq
35{
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 Thomaiyar6e1ba9e2018-11-29 06:29:21 +053063/** @struct getChannelAccessReq
64 *
65 * Structure for get channel access request command (refer spec sec 22.23)
66 */
AppaRao Puli071f3f22018-05-24 16:45:30 +053067struct getChannelAccessReq
68{
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 Thomaiyar6e1ba9e2018-11-29 06:29:21 +053083/** @struct getChannelAccessResp
84 *
85 * Structure for get channel access response command (refer spec sec 22.23)
86 */
AppaRao Puli071f3f22018-05-24 16:45:30 +053087struct getChannelAccessResp
88{
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 Thomaiyar6e1ba9e2018-11-29 06:29:21 +0530109/** @struct getChannelInfoReq
110 *
111 * Structure for get channel info request command (refer spec sec 22.24)
112 */
AppaRao Puli071f3f22018-05-24 16:45:30 +0530113struct getChannelInfoReq
114{
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 Thomaiyar6e1ba9e2018-11-29 06:29:21 +0530125/** @struct getChannelInfoResp
126 *
127 * Structure for get channel info response command (refer spec sec 22.24)
128 */
AppaRao Puli071f3f22018-05-24 16:45:30 +0530129struct getChannelInfoResp
130{
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{
161 const setChannelAccessReq* req = static_cast<setChannelAccessReq*>(request);
162 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
172 // TODO: Self channel number (0xE) has to be determined.
173 uint8_t chNum = req->chNum;
174 if (!isValidChannel(chNum))
175 {
176 log<level::DEBUG>("Set channel access - Parameter out of range");
177 return IPMI_CC_INVALID_FIELD_REQUEST;
178 }
179
180 if (EChannelSessSupported::none == getChannelSessionSupport(chNum))
181 {
182 log<level::DEBUG>("Set channel access - No support on channel");
183 return IPMI_CC_ACTION_NOT_SUPPORTED_FOR_CHANNEL;
184 }
185
186 ChannelAccess chActData;
187 ChannelAccess chNVData;
188 uint8_t setActFlag = 0;
189 uint8_t setNVFlag = 0;
190 ipmi_ret_t compCode = IPMI_CC_OK;
191
192 switch (req->accessSetMode)
193 {
194 case doNotSet:
195 // Do nothing
196 break;
197 case nvData:
198 chNVData.accessMode = req->accessMode;
199 chNVData.userAuthDisabled = req->usrAuthDisabled;
200 chNVData.perMsgAuthDisabled = req->msgAuthDisabled;
201 chNVData.alertingDisabled = req->alertDisabled;
202 setNVFlag |= (setAccessMode | setUserAuthEnabled |
203 setMsgAuthEnabled | setAlertingEnabled);
204 break;
205 case activeData:
206 chActData.accessMode = req->accessMode;
207 chActData.userAuthDisabled = req->usrAuthDisabled;
208 chActData.perMsgAuthDisabled = req->msgAuthDisabled;
209 chActData.alertingDisabled = req->alertDisabled;
210 setActFlag |= (setAccessMode | setUserAuthEnabled |
211 setMsgAuthEnabled | setAlertingEnabled);
212 break;
213 case reserved:
214 default:
215 log<level::DEBUG>("Set channel access - Invalid access set mode");
216 return IPMI_CC_INVALID_FIELD_REQUEST;
217 }
218
219 switch (req->privSetMode)
220 {
221 case doNotSet:
222 // Do nothing
223 break;
224 case nvData:
225 chNVData.privLimit = req->privLimit;
226 setNVFlag |= setPrivLimit;
227 break;
228 case activeData:
229 chActData.privLimit = req->privLimit;
230 setActFlag |= setPrivLimit;
231 break;
232 case reserved:
233 default:
234 log<level::DEBUG>("Set channel access - Invalid access priv mode");
235 return IPMI_CC_INVALID_FIELD_REQUEST;
236 }
237
238 if (setNVFlag != 0)
239 {
240 compCode = setChannelAccessPersistData(chNum, chNVData, setNVFlag);
241 if (compCode != IPMI_CC_OK)
242 {
243 log<level::DEBUG>("Set channel access - Failed to set access data");
244 return compCode;
245 }
246 }
247
248 if (setActFlag != 0)
249 {
250 compCode = setChannelAccessData(chNum, chActData, setActFlag);
251 if (compCode != IPMI_CC_OK)
252 {
253 log<level::DEBUG>("Set channel access - Failed to set access data");
254 return compCode;
255 }
256 }
257
258 return IPMI_CC_OK;
259}
260
261ipmi_ret_t ipmiGetChannelAccess(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
262 ipmi_request_t request,
263 ipmi_response_t response,
264 ipmi_data_len_t data_len,
265 ipmi_context_t context)
266{
267 const getChannelAccessReq* req = static_cast<getChannelAccessReq*>(request);
268 size_t reqLength = *data_len;
269
270 *data_len = 0;
271
272 if (reqLength != sizeof(*req))
273 {
274 log<level::DEBUG>("Get channel access - Invalid Length");
275 return IPMI_CC_REQ_DATA_LEN_INVALID;
276 }
277
278 // TODO: Self channel number (0xE) has to be determined.
279 uint8_t chNum = req->chNum;
280 if (!isValidChannel(chNum))
281 {
282 log<level::DEBUG>("Get channel access - Parameter out of range");
283 return IPMI_CC_INVALID_FIELD_REQUEST;
284 }
285
286 if ((req->accessSetMode == doNotSet) || (req->accessSetMode == reserved))
287 {
288 log<level::DEBUG>("Get channel access - Invalid Access mode");
289 return IPMI_CC_INVALID_FIELD_REQUEST;
290 }
291
292 if (EChannelSessSupported::none == getChannelSessionSupport(chNum))
293 {
294 log<level::DEBUG>("Get channel access - No support on channel");
295 return IPMI_CC_ACTION_NOT_SUPPORTED_FOR_CHANNEL;
296 }
297
298 getChannelAccessResp* resp = static_cast<getChannelAccessResp*>(response);
299
300 std::fill(reinterpret_cast<uint8_t*>(resp),
301 reinterpret_cast<uint8_t*>(resp) + sizeof(*resp), 0);
302
303 ChannelAccess chAccess;
304 ipmi_ret_t compCode = IPMI_CC_OK;
305
306 if (req->accessSetMode == nvData)
307 {
308 compCode = getChannelAccessPersistData(chNum, chAccess);
309 }
310 else if (req->accessSetMode == activeData)
311 {
312 compCode = getChannelAccessData(chNum, chAccess);
313 }
314
315 if (compCode != IPMI_CC_OK)
316 {
317 return compCode;
318 }
319
320 resp->accessMode = chAccess.accessMode;
321 resp->usrAuthDisabled = chAccess.userAuthDisabled;
322 resp->msgAuthDisabled = chAccess.perMsgAuthDisabled;
323 resp->alertDisabled = chAccess.alertingDisabled;
324 resp->privLimit = chAccess.privLimit;
325
326 *data_len = sizeof(*resp);
327 return IPMI_CC_OK;
328}
329
330ipmi_ret_t ipmiGetChannelInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
331 ipmi_request_t request, ipmi_response_t response,
332 ipmi_data_len_t data_len, ipmi_context_t context)
333{
334 const getChannelInfoReq* req = static_cast<getChannelInfoReq*>(request);
335 size_t reqLength = *data_len;
336
337 *data_len = 0;
338
339 if (reqLength != sizeof(*req))
340 {
341 log<level::DEBUG>("Get channel info - Invalid Length");
342 return IPMI_CC_REQ_DATA_LEN_INVALID;
343 }
344
345 // TODO: Self channel number (0xE) has to be determined.
346 uint8_t chNum = req->chNum;
347 if (!isValidChannel(chNum))
348 {
349 log<level::DEBUG>("Get channel info - Parameter out of range");
350 return IPMI_CC_INVALID_FIELD_REQUEST;
351 }
352
353 // Check the existance of device for session-less channels.
354 if ((EChannelSessSupported::none != getChannelSessionSupport(chNum)) &&
355 (!(doesDeviceExist(chNum))))
356 {
357 log<level::DEBUG>("Get channel info - Device not exist");
358 return IPMI_CC_PARM_OUT_OF_RANGE;
359 }
360
361 getChannelInfoResp* resp = static_cast<getChannelInfoResp*>(response);
362
363 std::fill(reinterpret_cast<uint8_t*>(resp),
364 reinterpret_cast<uint8_t*>(resp) + sizeof(*resp), 0);
365
366 ChannelInfo chInfo;
367 ipmi_ret_t compCode = getChannelInfo(chNum, chInfo);
368 if (compCode != IPMI_CC_OK)
369 {
370 return compCode;
371 }
372
373 resp->chNum = chNum;
374 resp->mediumType = chInfo.mediumType;
375 resp->msgProtType = chInfo.protocolType;
376 resp->actSessCount = getChannelActiveSessions(chNum);
377 resp->sessType = chInfo.sessionSupported;
378
379 // IPMI Spec: The IPMI Enterprise Number is: 7154 (decimal)
380 resp->vendorId[0] = 0xF2;
381 resp->vendorId[1] = 0x1B;
382 resp->vendorId[2] = 0x00;
383
384 // Auxiliary Channel info - byte 1:2
385 // TODO: For System Interface(0xF) and OEM channel types, this needs
386 // to be changed acoordingly.
387 // All other channel types, its reverved
388 resp->auxChInfo[0] = 0x00;
389 resp->auxChInfo[1] = 0x00;
390
391 *data_len = sizeof(*resp);
392
393 return IPMI_CC_OK;
394}
395
396void registerChannelFunctions()
397{
398 ipmiChannelInit();
399
400 ipmi_register_callback(NETFUN_APP, IPMI_CMD_SET_CHANNEL_ACCESS, NULL,
401 ipmiSetChannelAccess, PRIVILEGE_ADMIN);
402
403 ipmi_register_callback(NETFUN_APP, IPMI_CMD_GET_CHANNEL_ACCESS, NULL,
404 ipmiGetChannelAccess, PRIVILEGE_USER);
405
406 ipmi_register_callback(NETFUN_APP, IPMI_CMD_GET_CHANNEL_INFO, NULL,
407 ipmiGetChannelInfo, PRIVILEGE_USER);
408 return;
409}
410
411} // namespace ipmi