1 /* 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 25 using namespace phosphor::logging; 26 27 namespace ipmi 28 { 29 30 /** @struct SetChannelAccessReq 31 * 32 * Structure for set channel access request command (refer spec sec 22.22) 33 */ 34 struct 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 63 /** @struct GetChannelAccessReq 64 * 65 * Structure for get channel access request command (refer spec sec 22.23) 66 */ 67 struct 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 83 /** @struct GetChannelAccessResp 84 * 85 * Structure for get channel access response command (refer spec sec 22.23) 86 */ 87 struct 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 109 /** @struct GetChannelInfoReq 110 * 111 * Structure for get channel info request command (refer spec sec 22.24) 112 */ 113 struct 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 125 /** @struct GetChannelInfoResp 126 * 127 * Structure for get channel info response command (refer spec sec 22.24) 128 */ 129 struct 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 155 ipmi_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 uint8_t chNum = convertCurrentChannelNum(req->chNum); 173 if (!isValidChannel(chNum) || req->reserved_1 != 0 || req->reserved_2 != 0) 174 { 175 log<level::DEBUG>("Set channel access - Invalid field in request"); 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 260 ipmi_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 { 266 const GetChannelAccessReq* req = static_cast<GetChannelAccessReq*>(request); 267 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 277 uint8_t chNum = convertCurrentChannelNum(req->chNum); 278 if (!isValidChannel(chNum) || req->reserved_1 != 0 || req->reserved_2 != 0) 279 { 280 log<level::DEBUG>("Get channel access - Invalid field in request"); 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 296 GetChannelAccessResp* resp = static_cast<GetChannelAccessResp*>(response); 297 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 328 ipmi_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 { 332 const GetChannelInfoReq* req = static_cast<GetChannelInfoReq*>(request); 333 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 343 uint8_t chNum = convertCurrentChannelNum(req->chNum); 344 if (!isValidChannel(chNum) || req->reserved_1 != 0) 345 { 346 log<level::DEBUG>("Get channel info - Invalid field in request"); 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 358 GetChannelInfoResp* resp = static_cast<GetChannelInfoResp*>(response); 359 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 393 void registerChannelFunctions() __attribute__((constructor)); 394 void 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 410