blob: c5ef8b777812fef247ac7deb698758ad9e09c1d8 [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
30struct setChannelAccessReq
31{
32#if BYTE_ORDER == LITTLE_ENDIAN
33 uint8_t chNum : 4;
34 uint8_t reserved_1 : 4;
35 uint8_t accessMode : 3;
36 uint8_t usrAuthDisabled : 1;
37 uint8_t msgAuthDisabled : 1;
38 uint8_t alertDisabled : 1;
39 uint8_t accessSetMode : 2;
40 uint8_t privLimit : 4;
41 uint8_t reserved_2 : 2;
42 uint8_t privSetMode : 2;
43#endif
44#if BYTE_ORDER == BIG_ENDIAN
45 uint8_t reserved_1 : 4;
46 uint8_t chNum : 4;
47 uint8_t accessSetMode : 2;
48 uint8_t alertDisabled : 1;
49 uint8_t msgAuthDisabled : 1;
50 uint8_t usrAuthDisabled : 1;
51 uint8_t accessMode : 3;
52 uint8_t privSetMode : 2;
53 uint8_t reserved_2 : 2;
54 uint8_t privLimit : 4;
55#endif
56
57} __attribute__((packed));
58
59struct getChannelAccessReq
60{
61#if BYTE_ORDER == LITTLE_ENDIAN
62 uint8_t chNum : 4;
63 uint8_t reserved_1 : 4;
64 uint8_t reserved_2 : 6;
65 uint8_t accessSetMode : 2;
66#endif
67#if BYTE_ORDER == BIG_ENDIAN
68 uint8_t reserved_1 : 4;
69 uint8_t chNum : 4;
70 uint8_t accessSetMode : 2;
71 uint8_t reserved_2 : 6;
72#endif
73} __attribute__((packed));
74
75struct getChannelAccessResp
76{
77#if BYTE_ORDER == LITTLE_ENDIAN
78 uint8_t accessMode : 3;
79 uint8_t usrAuthDisabled : 1;
80 uint8_t msgAuthDisabled : 1;
81 uint8_t alertDisabled : 1;
82 uint8_t reserved_1 : 2;
83 uint8_t privLimit : 4;
84 uint8_t reserved_2 : 4;
85#endif
86#if BYTE_ORDER == BIG_ENDIAN
87 uint8_t reserved_1 : 2;
88 uint8_t alertDisabled : 1;
89 uint8_t msgAuthDisabled : 1;
90 uint8_t usrAuthDisabled : 1;
91 uint8_t accessMode : 3;
92 uint8_t reserved_2 : 4;
93 uint8_t privLimit : 4;
94#endif
95} __attribute__((packed));
96
97struct getChannelInfoReq
98{
99#if BYTE_ORDER == LITTLE_ENDIAN
100 uint8_t chNum : 4;
101 uint8_t reserved_1 : 4;
102#endif
103#if BYTE_ORDER == BIG_ENDIAN
104 uint8_t reserved_1 : 4;
105 uint8_t chNum : 4;
106#endif
107} __attribute__((packed));
108
109struct getChannelInfoResp
110{
111#if BYTE_ORDER == LITTLE_ENDIAN
112 uint8_t chNum : 4;
113 uint8_t reserved_1 : 4;
114 uint8_t mediumType : 7;
115 uint8_t reserved_2 : 1;
116 uint8_t msgProtType : 5;
117 uint8_t reserved_3 : 3;
118 uint8_t actSessCount : 6;
119 uint8_t sessType : 2;
120#endif
121#if BYTE_ORDER == BIG_ENDIAN
122 uint8_t reserved_1 : 4;
123 uint8_t chNum : 4;
124 uint8_t reserved_2 : 1;
125 uint8_t mediumType : 7;
126 uint8_t reserved_3 : 3;
127 uint8_t msgProtType : 5;
128 uint8_t sessType : 2;
129 uint8_t actSessCount : 6;
130#endif
131 uint8_t vendorId[3];
132 uint8_t auxChInfo[2];
133} __attribute__((packed));
134
135ipmi_ret_t ipmiSetChannelAccess(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
136 ipmi_request_t request,
137 ipmi_response_t response,
138 ipmi_data_len_t data_len,
139 ipmi_context_t context)
140{
141 const setChannelAccessReq* req = static_cast<setChannelAccessReq*>(request);
142 size_t reqLength = *data_len;
143
144 *data_len = 0;
145
146 if (reqLength != sizeof(*req))
147 {
148 log<level::DEBUG>("Set channel access - Invalid Length");
149 return IPMI_CC_REQ_DATA_LEN_INVALID;
150 }
151
152 // TODO: Self channel number (0xE) has to be determined.
153 uint8_t chNum = req->chNum;
154 if (!isValidChannel(chNum))
155 {
156 log<level::DEBUG>("Set channel access - Parameter out of range");
157 return IPMI_CC_INVALID_FIELD_REQUEST;
158 }
159
160 if (EChannelSessSupported::none == getChannelSessionSupport(chNum))
161 {
162 log<level::DEBUG>("Set channel access - No support on channel");
163 return IPMI_CC_ACTION_NOT_SUPPORTED_FOR_CHANNEL;
164 }
165
166 ChannelAccess chActData;
167 ChannelAccess chNVData;
168 uint8_t setActFlag = 0;
169 uint8_t setNVFlag = 0;
170 ipmi_ret_t compCode = IPMI_CC_OK;
171
172 switch (req->accessSetMode)
173 {
174 case doNotSet:
175 // Do nothing
176 break;
177 case nvData:
178 chNVData.accessMode = req->accessMode;
179 chNVData.userAuthDisabled = req->usrAuthDisabled;
180 chNVData.perMsgAuthDisabled = req->msgAuthDisabled;
181 chNVData.alertingDisabled = req->alertDisabled;
182 setNVFlag |= (setAccessMode | setUserAuthEnabled |
183 setMsgAuthEnabled | setAlertingEnabled);
184 break;
185 case activeData:
186 chActData.accessMode = req->accessMode;
187 chActData.userAuthDisabled = req->usrAuthDisabled;
188 chActData.perMsgAuthDisabled = req->msgAuthDisabled;
189 chActData.alertingDisabled = req->alertDisabled;
190 setActFlag |= (setAccessMode | setUserAuthEnabled |
191 setMsgAuthEnabled | setAlertingEnabled);
192 break;
193 case reserved:
194 default:
195 log<level::DEBUG>("Set channel access - Invalid access set mode");
196 return IPMI_CC_INVALID_FIELD_REQUEST;
197 }
198
199 switch (req->privSetMode)
200 {
201 case doNotSet:
202 // Do nothing
203 break;
204 case nvData:
205 chNVData.privLimit = req->privLimit;
206 setNVFlag |= setPrivLimit;
207 break;
208 case activeData:
209 chActData.privLimit = req->privLimit;
210 setActFlag |= setPrivLimit;
211 break;
212 case reserved:
213 default:
214 log<level::DEBUG>("Set channel access - Invalid access priv mode");
215 return IPMI_CC_INVALID_FIELD_REQUEST;
216 }
217
218 if (setNVFlag != 0)
219 {
220 compCode = setChannelAccessPersistData(chNum, chNVData, setNVFlag);
221 if (compCode != IPMI_CC_OK)
222 {
223 log<level::DEBUG>("Set channel access - Failed to set access data");
224 return compCode;
225 }
226 }
227
228 if (setActFlag != 0)
229 {
230 compCode = setChannelAccessData(chNum, chActData, setActFlag);
231 if (compCode != IPMI_CC_OK)
232 {
233 log<level::DEBUG>("Set channel access - Failed to set access data");
234 return compCode;
235 }
236 }
237
238 return IPMI_CC_OK;
239}
240
241ipmi_ret_t ipmiGetChannelAccess(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
242 ipmi_request_t request,
243 ipmi_response_t response,
244 ipmi_data_len_t data_len,
245 ipmi_context_t context)
246{
247 const getChannelAccessReq* req = static_cast<getChannelAccessReq*>(request);
248 size_t reqLength = *data_len;
249
250 *data_len = 0;
251
252 if (reqLength != sizeof(*req))
253 {
254 log<level::DEBUG>("Get channel access - Invalid Length");
255 return IPMI_CC_REQ_DATA_LEN_INVALID;
256 }
257
258 // TODO: Self channel number (0xE) has to be determined.
259 uint8_t chNum = req->chNum;
260 if (!isValidChannel(chNum))
261 {
262 log<level::DEBUG>("Get channel access - Parameter out of range");
263 return IPMI_CC_INVALID_FIELD_REQUEST;
264 }
265
266 if ((req->accessSetMode == doNotSet) || (req->accessSetMode == reserved))
267 {
268 log<level::DEBUG>("Get channel access - Invalid Access mode");
269 return IPMI_CC_INVALID_FIELD_REQUEST;
270 }
271
272 if (EChannelSessSupported::none == getChannelSessionSupport(chNum))
273 {
274 log<level::DEBUG>("Get channel access - No support on channel");
275 return IPMI_CC_ACTION_NOT_SUPPORTED_FOR_CHANNEL;
276 }
277
278 getChannelAccessResp* resp = static_cast<getChannelAccessResp*>(response);
279
280 std::fill(reinterpret_cast<uint8_t*>(resp),
281 reinterpret_cast<uint8_t*>(resp) + sizeof(*resp), 0);
282
283 ChannelAccess chAccess;
284 ipmi_ret_t compCode = IPMI_CC_OK;
285
286 if (req->accessSetMode == nvData)
287 {
288 compCode = getChannelAccessPersistData(chNum, chAccess);
289 }
290 else if (req->accessSetMode == activeData)
291 {
292 compCode = getChannelAccessData(chNum, chAccess);
293 }
294
295 if (compCode != IPMI_CC_OK)
296 {
297 return compCode;
298 }
299
300 resp->accessMode = chAccess.accessMode;
301 resp->usrAuthDisabled = chAccess.userAuthDisabled;
302 resp->msgAuthDisabled = chAccess.perMsgAuthDisabled;
303 resp->alertDisabled = chAccess.alertingDisabled;
304 resp->privLimit = chAccess.privLimit;
305
306 *data_len = sizeof(*resp);
307 return IPMI_CC_OK;
308}
309
310ipmi_ret_t ipmiGetChannelInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
311 ipmi_request_t request, ipmi_response_t response,
312 ipmi_data_len_t data_len, ipmi_context_t context)
313{
314 const getChannelInfoReq* req = static_cast<getChannelInfoReq*>(request);
315 size_t reqLength = *data_len;
316
317 *data_len = 0;
318
319 if (reqLength != sizeof(*req))
320 {
321 log<level::DEBUG>("Get channel info - Invalid Length");
322 return IPMI_CC_REQ_DATA_LEN_INVALID;
323 }
324
325 // TODO: Self channel number (0xE) has to be determined.
326 uint8_t chNum = req->chNum;
327 if (!isValidChannel(chNum))
328 {
329 log<level::DEBUG>("Get channel info - Parameter out of range");
330 return IPMI_CC_INVALID_FIELD_REQUEST;
331 }
332
333 // Check the existance of device for session-less channels.
334 if ((EChannelSessSupported::none != getChannelSessionSupport(chNum)) &&
335 (!(doesDeviceExist(chNum))))
336 {
337 log<level::DEBUG>("Get channel info - Device not exist");
338 return IPMI_CC_PARM_OUT_OF_RANGE;
339 }
340
341 getChannelInfoResp* resp = static_cast<getChannelInfoResp*>(response);
342
343 std::fill(reinterpret_cast<uint8_t*>(resp),
344 reinterpret_cast<uint8_t*>(resp) + sizeof(*resp), 0);
345
346 ChannelInfo chInfo;
347 ipmi_ret_t compCode = getChannelInfo(chNum, chInfo);
348 if (compCode != IPMI_CC_OK)
349 {
350 return compCode;
351 }
352
353 resp->chNum = chNum;
354 resp->mediumType = chInfo.mediumType;
355 resp->msgProtType = chInfo.protocolType;
356 resp->actSessCount = getChannelActiveSessions(chNum);
357 resp->sessType = chInfo.sessionSupported;
358
359 // IPMI Spec: The IPMI Enterprise Number is: 7154 (decimal)
360 resp->vendorId[0] = 0xF2;
361 resp->vendorId[1] = 0x1B;
362 resp->vendorId[2] = 0x00;
363
364 // Auxiliary Channel info - byte 1:2
365 // TODO: For System Interface(0xF) and OEM channel types, this needs
366 // to be changed acoordingly.
367 // All other channel types, its reverved
368 resp->auxChInfo[0] = 0x00;
369 resp->auxChInfo[1] = 0x00;
370
371 *data_len = sizeof(*resp);
372
373 return IPMI_CC_OK;
374}
375
376void registerChannelFunctions()
377{
378 ipmiChannelInit();
379
380 ipmi_register_callback(NETFUN_APP, IPMI_CMD_SET_CHANNEL_ACCESS, NULL,
381 ipmiSetChannelAccess, PRIVILEGE_ADMIN);
382
383 ipmi_register_callback(NETFUN_APP, IPMI_CMD_GET_CHANNEL_ACCESS, NULL,
384 ipmiGetChannelAccess, PRIVILEGE_USER);
385
386 ipmi_register_callback(NETFUN_APP, IPMI_CMD_GET_CHANNEL_INFO, NULL,
387 ipmiGetChannelInfo, PRIVILEGE_USER);
388 return;
389}
390
391} // namespace ipmi