blob: 9c633ecff938d8f704229dd54d46184133647556 [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
NITIN SHARMA89e4bf22019-05-02 13:03:58 +000022#include <ipmid/api.hpp>
AppaRao Puli071f3f22018-05-24 16:45:30 +053023#include <phosphor-logging/log.hpp>
24#include <regex>
25
26using namespace phosphor::logging;
27
28namespace ipmi
29{
30
Saravanan Palanisamyb5a0f162019-03-04 18:34:44 +053031/** @struct GetChannelPayloadSupportReq
32 *
33 * Structure for get channel payload support command request (refer spec
34 * sec 24.8)
35 */
36struct GetChannelPayloadSupportReq
37{
38#if BYTE_ORDER == LITTLE_ENDIAN
39 uint8_t chNum : 4;
40 uint8_t reserved : 4;
41#endif
42#if BYTE_ORDER == BIG_ENDIAN
43 uint8_t reserved : 4;
44 uint8_t chNum : 4;
45#endif
46} __attribute__((packed));
47
48/** @struct GetChannelPayloadSupportResp
49 *
50 * Structure for get channel payload support command response (refer spec
51 * sec 24.8)
52 */
53struct GetChannelPayloadSupportResp
54{
55 uint8_t stdPayloadType[2];
56 uint8_t sessSetupPayloadType[2];
57 uint8_t OEMPayloadType[2];
58 uint8_t reserved[2];
59} __attribute__((packed));
60
NITIN SHARMA89e4bf22019-05-02 13:03:58 +000061/** @brief implements the set channel access command
62 * @ param ctx - context pointer
63 * @ param channel - channel number
64 * @ param reserved - skip 4 bits
65 * @ param accessMode - access mode for IPMI messaging
66 * @ param usrAuth - user level authentication (enable/disable)
67 * @ param msgAuth - per message authentication (enable/disable)
68 * @ param alertDisabled - PEF alerting (enable/disable)
69 * @ param chanAccess - channel access
70 * @ param channelPrivLimit - channel privilege limit
71 * @ param reserved - skip 3 bits
72 * @ param channelPrivMode - channel priviledge mode
73 *
74 * @ returns IPMI completion code
75 **/
76RspType<> ipmiSetChannelAccess(Context::ptr ctx, uint4_t channel,
77 uint4_t reserved1, uint3_t accessMode,
78 bool usrAuth, bool msgAuth, bool alertDisabled,
79 uint2_t chanAccess, uint4_t channelPrivLimit,
80 uint2_t reserved2, uint2_t channelPrivMode)
AppaRao Puli071f3f22018-05-24 16:45:30 +053081{
NITIN SHARMA89e4bf22019-05-02 13:03:58 +000082 const uint8_t chNum =
83 convertCurrentChannelNum(static_cast<uint8_t>(channel), ctx->channel);
AppaRao Puli071f3f22018-05-24 16:45:30 +053084
NITIN SHARMA89e4bf22019-05-02 13:03:58 +000085 if (!isValidChannel(chNum) || reserved1 != 0 || reserved2 != 0)
AppaRao Puli071f3f22018-05-24 16:45:30 +053086 {
Richard Marian Thomaiyaref024012019-01-29 11:06:39 +053087 log<level::DEBUG>("Set channel access - Invalid field in request");
NITIN SHARMA89e4bf22019-05-02 13:03:58 +000088 return responseInvalidFieldRequest();
AppaRao Puli071f3f22018-05-24 16:45:30 +053089 }
90
NITIN SHARMA89e4bf22019-05-02 13:03:58 +000091 if (getChannelSessionSupport(chNum) == EChannelSessSupported::none)
AppaRao Puli071f3f22018-05-24 16:45:30 +053092 {
93 log<level::DEBUG>("Set channel access - No support on channel");
NITIN SHARMA89e4bf22019-05-02 13:03:58 +000094 return responseInvalidFieldRequest();
AppaRao Puli071f3f22018-05-24 16:45:30 +053095 }
96
97 ChannelAccess chActData;
98 ChannelAccess chNVData;
99 uint8_t setActFlag = 0;
100 uint8_t setNVFlag = 0;
NITIN SHARMA89e4bf22019-05-02 13:03:58 +0000101 Cc compCode;
AppaRao Puli071f3f22018-05-24 16:45:30 +0530102
NITIN SHARMA89e4bf22019-05-02 13:03:58 +0000103 // cannot static cast directly from uint2_t to enum; must go via int
104 uint8_t channelAccessAction = static_cast<uint8_t>(chanAccess);
105 switch (static_cast<EChannelActionType>(channelAccessAction))
AppaRao Puli071f3f22018-05-24 16:45:30 +0530106 {
107 case doNotSet:
AppaRao Puli071f3f22018-05-24 16:45:30 +0530108 break;
109 case nvData:
NITIN SHARMA89e4bf22019-05-02 13:03:58 +0000110 chNVData.accessMode = static_cast<uint8_t>(accessMode);
111 chNVData.userAuthDisabled = usrAuth;
112 chNVData.perMsgAuthDisabled = msgAuth;
113 chNVData.alertingDisabled = alertDisabled;
AppaRao Puli071f3f22018-05-24 16:45:30 +0530114 setNVFlag |= (setAccessMode | setUserAuthEnabled |
115 setMsgAuthEnabled | setAlertingEnabled);
116 break;
NITIN SHARMA89e4bf22019-05-02 13:03:58 +0000117
AppaRao Puli071f3f22018-05-24 16:45:30 +0530118 case activeData:
NITIN SHARMA89e4bf22019-05-02 13:03:58 +0000119 chActData.accessMode = static_cast<uint8_t>(accessMode);
120 chActData.userAuthDisabled = usrAuth;
121 chActData.perMsgAuthDisabled = msgAuth;
122 chActData.alertingDisabled = alertDisabled;
AppaRao Puli071f3f22018-05-24 16:45:30 +0530123 setActFlag |= (setAccessMode | setUserAuthEnabled |
124 setMsgAuthEnabled | setAlertingEnabled);
125 break;
NITIN SHARMA89e4bf22019-05-02 13:03:58 +0000126
AppaRao Puli071f3f22018-05-24 16:45:30 +0530127 case reserved:
128 default:
129 log<level::DEBUG>("Set channel access - Invalid access set mode");
NITIN SHARMA89e4bf22019-05-02 13:03:58 +0000130 return responseInvalidFieldRequest();
AppaRao Puli071f3f22018-05-24 16:45:30 +0530131 }
132
NITIN SHARMA89e4bf22019-05-02 13:03:58 +0000133 // cannot static cast directly from uint2_t to enum; must go via int
134 uint8_t channelPrivAction = static_cast<uint8_t>(channelPrivMode);
135 switch (static_cast<EChannelActionType>(channelPrivAction))
AppaRao Puli071f3f22018-05-24 16:45:30 +0530136 {
137 case doNotSet:
AppaRao Puli071f3f22018-05-24 16:45:30 +0530138 break;
139 case nvData:
NITIN SHARMA89e4bf22019-05-02 13:03:58 +0000140 chNVData.privLimit = static_cast<uint8_t>(channelPrivLimit);
AppaRao Puli071f3f22018-05-24 16:45:30 +0530141 setNVFlag |= setPrivLimit;
142 break;
143 case activeData:
NITIN SHARMA89e4bf22019-05-02 13:03:58 +0000144 chActData.privLimit = static_cast<uint8_t>(channelPrivLimit);
145
AppaRao Puli071f3f22018-05-24 16:45:30 +0530146 setActFlag |= setPrivLimit;
147 break;
148 case reserved:
149 default:
150 log<level::DEBUG>("Set channel access - Invalid access priv mode");
NITIN SHARMA89e4bf22019-05-02 13:03:58 +0000151 return responseInvalidFieldRequest();
AppaRao Puli071f3f22018-05-24 16:45:30 +0530152 }
153
154 if (setNVFlag != 0)
155 {
156 compCode = setChannelAccessPersistData(chNum, chNVData, setNVFlag);
157 if (compCode != IPMI_CC_OK)
158 {
159 log<level::DEBUG>("Set channel access - Failed to set access data");
NITIN SHARMA89e4bf22019-05-02 13:03:58 +0000160 return response(compCode);
AppaRao Puli071f3f22018-05-24 16:45:30 +0530161 }
162 }
163
164 if (setActFlag != 0)
165 {
166 compCode = setChannelAccessData(chNum, chActData, setActFlag);
167 if (compCode != IPMI_CC_OK)
168 {
169 log<level::DEBUG>("Set channel access - Failed to set access data");
NITIN SHARMA89e4bf22019-05-02 13:03:58 +0000170 return response(compCode);
AppaRao Puli071f3f22018-05-24 16:45:30 +0530171 }
172 }
173
NITIN SHARMA89e4bf22019-05-02 13:03:58 +0000174 return responseSuccess();
AppaRao Puli071f3f22018-05-24 16:45:30 +0530175}
176
Richard Marian Thomaiyarbc5e9ba2019-05-07 13:32:48 +0530177/** @brief implements the get channel access command
178 * @ param ctx - context pointer
179 * @ param channel - channel number
180 * @ param reserved1 - skip 4 bits
181 * @ param reserved2 - skip 6 bits
182 * @ param accessMode - get access mode
183 *
184 * @returns ipmi completion code plus response data
185 * - accessMode - get access mode
186 * - usrAuthDisabled - user level authentication status
187 * - msgAuthDisabled - message level authentication status
188 * - alertDisabled - alerting status
189 * - reserved - skip 2 bits
190 * - privLimit - channel privilege limit
191 * - reserved - skip 4 bits
192 * */
193ipmi ::RspType<uint3_t, // access mode,
194 bool, // user authentication status,
195 bool, // message authentication status,
196 bool, // alerting status,
197 uint2_t, // reserved,
198
199 uint4_t, // channel privilege,
200 uint4_t // reserved
201 >
202 ipmiGetChannelAccess(Context::ptr ctx, uint4_t channel, uint4_t reserved1,
203 uint6_t reserved2, uint2_t accessSetMode)
AppaRao Puli071f3f22018-05-24 16:45:30 +0530204{
Richard Marian Thomaiyarbc5e9ba2019-05-07 13:32:48 +0530205 const uint8_t chNum =
206 convertCurrentChannelNum(static_cast<uint8_t>(channel), ctx->channel);
AppaRao Puli071f3f22018-05-24 16:45:30 +0530207
Richard Marian Thomaiyarbc5e9ba2019-05-07 13:32:48 +0530208 if (!isValidChannel(chNum) || reserved1 != 0 || reserved2 != 0)
AppaRao Puli071f3f22018-05-24 16:45:30 +0530209 {
Richard Marian Thomaiyaref024012019-01-29 11:06:39 +0530210 log<level::DEBUG>("Get channel access - Invalid field in request");
Richard Marian Thomaiyarbc5e9ba2019-05-07 13:32:48 +0530211 return responseInvalidFieldRequest();
AppaRao Puli071f3f22018-05-24 16:45:30 +0530212 }
213
Richard Marian Thomaiyarbc5e9ba2019-05-07 13:32:48 +0530214 if ((accessSetMode == doNotSet) || (accessSetMode == reserved))
AppaRao Puli071f3f22018-05-24 16:45:30 +0530215 {
216 log<level::DEBUG>("Get channel access - Invalid Access mode");
Richard Marian Thomaiyarbc5e9ba2019-05-07 13:32:48 +0530217 return responseInvalidFieldRequest();
AppaRao Puli071f3f22018-05-24 16:45:30 +0530218 }
219
Richard Marian Thomaiyarbc5e9ba2019-05-07 13:32:48 +0530220 if (getChannelSessionSupport(chNum) == EChannelSessSupported::none)
AppaRao Puli071f3f22018-05-24 16:45:30 +0530221 {
222 log<level::DEBUG>("Get channel access - No support on channel");
Richard Marian Thomaiyarbc5e9ba2019-05-07 13:32:48 +0530223 return response(IPMI_CC_ACTION_NOT_SUPPORTED_FOR_CHANNEL);
AppaRao Puli071f3f22018-05-24 16:45:30 +0530224 }
225
AppaRao Puli071f3f22018-05-24 16:45:30 +0530226 ChannelAccess chAccess;
AppaRao Puli071f3f22018-05-24 16:45:30 +0530227
Richard Marian Thomaiyarbc5e9ba2019-05-07 13:32:48 +0530228 Cc compCode;
229
230 if (accessSetMode == nvData)
AppaRao Puli071f3f22018-05-24 16:45:30 +0530231 {
232 compCode = getChannelAccessPersistData(chNum, chAccess);
233 }
Richard Marian Thomaiyarbc5e9ba2019-05-07 13:32:48 +0530234 else if (accessSetMode == activeData)
AppaRao Puli071f3f22018-05-24 16:45:30 +0530235 {
236 compCode = getChannelAccessData(chNum, chAccess);
237 }
238
239 if (compCode != IPMI_CC_OK)
240 {
Richard Marian Thomaiyarbc5e9ba2019-05-07 13:32:48 +0530241 return response(compCode);
AppaRao Puli071f3f22018-05-24 16:45:30 +0530242 }
243
Richard Marian Thomaiyarbc5e9ba2019-05-07 13:32:48 +0530244 constexpr uint2_t reservedOut1 = 0;
245 constexpr uint4_t reservedOut2 = 0;
AppaRao Puli071f3f22018-05-24 16:45:30 +0530246
Richard Marian Thomaiyarbc5e9ba2019-05-07 13:32:48 +0530247 return responseSuccess(
248 static_cast<uint3_t>(chAccess.accessMode), chAccess.userAuthDisabled,
249 chAccess.perMsgAuthDisabled, chAccess.alertingDisabled, reservedOut1,
250 static_cast<uint4_t>(chAccess.privLimit), reservedOut2);
AppaRao Puli071f3f22018-05-24 16:45:30 +0530251}
252
Vernon Mauery6f1e9782019-05-02 16:31:07 -0700253/** @brief implements the get channel info command
254 * @ param ctx - context pointer
255 * @ param channel - channel number
256 * @ param reserved - skip 4 bits
257 *
258 * @returns ipmi completion code plus response data
259 * - chNum - the channel number for this request
260 * - mediumType - see Table 6-3, Channel Medium Type Numbers
261 * - protocolType - Table 6-2, Channel Protocol Type Numbers
262 * - activeSessionCount - number of active sessions
263 * - sessionType - channel support for sessions
264 * - vendorId - vendor for this channel protocol (IPMI - 7154)
265 * - auxChInfo - auxiliary info for channel
266 * */
267RspType<uint4_t, // chNum
268 uint4_t, // reserved
269 uint7_t, // mediumType
270 bool, // reserved
271 uint5_t, // protocolType
272 uint3_t, // reserved
273 uint6_t, // activeSessionCount
274 uint2_t, // sessionType
275 uint24_t, // Vendor IANA
276 uint16_t // aux info
277 >
278 ipmiGetChannelInfo(Context::ptr ctx, uint4_t channel, uint4_t reserved)
AppaRao Puli071f3f22018-05-24 16:45:30 +0530279{
Vernon Mauery6f1e9782019-05-02 16:31:07 -0700280 uint8_t chNum =
281 convertCurrentChannelNum(static_cast<uint8_t>(channel), ctx->channel);
282 if (!isValidChannel(chNum) || reserved)
AppaRao Puli071f3f22018-05-24 16:45:30 +0530283 {
Vernon Mauery6f1e9782019-05-02 16:31:07 -0700284 log<level::DEBUG>("Get channel access - Invalid field in request");
285 return responseInvalidFieldRequest();
AppaRao Puli071f3f22018-05-24 16:45:30 +0530286 }
287
AppaRao Puli071f3f22018-05-24 16:45:30 +0530288 ChannelInfo chInfo;
Vernon Mauery6f1e9782019-05-02 16:31:07 -0700289 Cc compCode = getChannelInfo(chNum, chInfo);
290 if (compCode != ccSuccess)
AppaRao Puli071f3f22018-05-24 16:45:30 +0530291 {
Vernon Mauery6f1e9782019-05-02 16:31:07 -0700292 log<level::ERR>("Failed to get channel info",
293 entry("CHANNEL=%x", chNum),
294 entry("ERRNO=%x", compCode));
295 return response(compCode);
AppaRao Puli071f3f22018-05-24 16:45:30 +0530296 }
297
Vernon Mauery6f1e9782019-05-02 16:31:07 -0700298 constexpr uint4_t reserved1 = 0;
299 constexpr bool reserved2 = false;
300 constexpr uint3_t reserved3 = 0;
301 uint8_t mediumType = chInfo.mediumType;
302 uint8_t protocolType = chInfo.protocolType;
303 uint2_t sessionType = chInfo.sessionSupported;
304 uint6_t activeSessionCount = getChannelActiveSessions(chNum);
AppaRao Puli071f3f22018-05-24 16:45:30 +0530305 // IPMI Spec: The IPMI Enterprise Number is: 7154 (decimal)
Vernon Mauery6f1e9782019-05-02 16:31:07 -0700306 constexpr uint24_t vendorId = 7154;
307 constexpr uint16_t auxChInfo = 0;
AppaRao Puli071f3f22018-05-24 16:45:30 +0530308
Vernon Mauery6f1e9782019-05-02 16:31:07 -0700309 return responseSuccess(chNum, reserved1, mediumType, reserved2,
310 protocolType, reserved3, activeSessionCount,
311 sessionType, vendorId, auxChInfo);
AppaRao Puli071f3f22018-05-24 16:45:30 +0530312}
313
Saravanan Palanisamyb5a0f162019-03-04 18:34:44 +0530314ipmi_ret_t ipmiGetChannelPayloadSupport(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
315 ipmi_request_t request,
316 ipmi_response_t response,
317 ipmi_data_len_t data_len,
318 ipmi_context_t context)
319{
320 const auto req = static_cast<GetChannelPayloadSupportReq*>(request);
321 size_t reqLength = *data_len;
322
323 *data_len = 0;
324
325 if (reqLength != sizeof(*req))
326 {
327 log<level::DEBUG>("Get channel payload - Invalid Length");
328 return IPMI_CC_REQ_DATA_LEN_INVALID;
329 }
330
331 uint8_t chNum = convertCurrentChannelNum(req->chNum);
332 if (!isValidChannel(chNum) || req->reserved != 0)
333 {
334 log<level::DEBUG>("Get channel payload - Invalid field in request");
335 return IPMI_CC_INVALID_FIELD_REQUEST;
336 }
337
338 // Not supported on sessionless channels.
339 if (EChannelSessSupported::none == getChannelSessionSupport(chNum))
340 {
341 log<level::DEBUG>("Get channel payload - Sessionless Channel");
342 return IPMI_CC_INVALID_FIELD_REQUEST;
343 }
344
345 // Session support is available in active LAN channels.
346 if ((EChannelSessSupported::none != getChannelSessionSupport(chNum)) &&
347 (!(doesDeviceExist(chNum))))
348 {
349 log<level::DEBUG>("Get channel payload - Device not exist");
350 return IPMI_CC_INVALID_FIELD_REQUEST;
351 }
352
353 auto resp = static_cast<GetChannelPayloadSupportResp*>(response);
354
355 std::fill(reinterpret_cast<uint8_t*>(resp),
356 reinterpret_cast<uint8_t*>(resp) + sizeof(*resp), 0);
357
358 // TODO: Hard coding for now.
359 // Mapping PayloadTypes to 'GetChannelPayloadSupportResp' fields:
360 // --------------------------------------------------------------
361 // Mask all except least 3 significant bits to get a value in the range of
362 // 0-7. This value maps to the bit position of given payload type in 'resp'
363 // fields.
364
365 static constexpr uint8_t payloadByteMask = 0x07;
366 static constexpr uint8_t stdPayloadTypeIPMI =
367 1 << (static_cast<uint8_t>(PayloadType::IPMI) & payloadByteMask);
368 static constexpr uint8_t stdPayloadTypeSOL =
369 1 << (static_cast<uint8_t>(PayloadType::SOL) & payloadByteMask);
370
371 static constexpr uint8_t sessPayloadTypeOpenReq =
372 1 << (static_cast<uint8_t>(PayloadType::OPEN_SESSION_REQUEST) &
373 payloadByteMask);
374 static constexpr uint8_t sessPayloadTypeRAKP1 =
375 1 << (static_cast<uint8_t>(PayloadType::RAKP1) & payloadByteMask);
376 static constexpr uint8_t sessPayloadTypeRAKP3 =
377 1 << (static_cast<uint8_t>(PayloadType::RAKP3) & payloadByteMask);
378
379 resp->stdPayloadType[0] = stdPayloadTypeIPMI | stdPayloadTypeSOL;
380 // RMCP+ Open Session request, RAKP Message1 and RAKP Message3.
381 resp->sessSetupPayloadType[0] =
382 sessPayloadTypeOpenReq | sessPayloadTypeRAKP1 | sessPayloadTypeRAKP3;
383
384 *data_len = sizeof(*resp);
385
386 return IPMI_CC_OK;
387}
388
William A. Kennington III343d0612018-12-10 15:56:24 -0800389void registerChannelFunctions() __attribute__((constructor));
AppaRao Puli071f3f22018-05-24 16:45:30 +0530390void registerChannelFunctions()
391{
392 ipmiChannelInit();
393
NITIN SHARMA89e4bf22019-05-02 13:03:58 +0000394 registerHandler(prioOpenBmcBase, netFnApp, app::cmdSetChannelAccess,
395 Privilege::Admin, ipmiSetChannelAccess);
AppaRao Puli071f3f22018-05-24 16:45:30 +0530396
Richard Marian Thomaiyarbc5e9ba2019-05-07 13:32:48 +0530397 registerHandler(prioOpenBmcBase, netFnApp, app::cmdGetChannelAccess,
398 Privilege::User, ipmiGetChannelAccess);
AppaRao Puli071f3f22018-05-24 16:45:30 +0530399
Vernon Mauery6f1e9782019-05-02 16:31:07 -0700400 registerHandler(prioOpenBmcBase, netFnApp, app::cmdGetChannelInfoCommand,
401 Privilege::User, ipmiGetChannelInfo);
Saravanan Palanisamyb5a0f162019-03-04 18:34:44 +0530402
403 ipmi_register_callback(NETFUN_APP, IPMI_CMD_GET_CHANNEL_PAYLOAD_SUPPORT,
404 NULL, ipmiGetChannelPayloadSupport, PRIVILEGE_USER);
405
AppaRao Puli071f3f22018-05-24 16:45:30 +0530406 return;
407}
408
409} // namespace ipmi