1 #include <host-ipmid/ipmid-api.h> 2 #include <phosphor-logging/log.hpp> 3 #include "main.hpp" 4 #include "payload_cmds.hpp" 5 #include "sol/sol_manager.hpp" 6 #include "sol_cmds.hpp" 7 8 namespace sol 9 { 10 11 namespace command 12 { 13 14 using namespace phosphor::logging; 15 16 std::vector<uint8_t> activatePayload(const std::vector<uint8_t>& inPayload, 17 const message::Handler& handler) 18 { 19 std::vector<uint8_t> outPayload(sizeof(ActivatePayloadResponse)); 20 auto request = reinterpret_cast<const ActivatePayloadRequest*> 21 (inPayload.data()); 22 auto response = reinterpret_cast<ActivatePayloadResponse*> 23 (outPayload.data()); 24 25 response->completionCode = IPMI_CC_OK; 26 27 // SOL is the payload currently supported for activation. 28 if (static_cast<uint8_t>(message::PayloadType::SOL) != request->payloadType) 29 { 30 response->completionCode = IPMI_CC_INVALID_FIELD_REQUEST; 31 return outPayload; 32 } 33 34 if (!std::get<sol::Manager&>(singletonPool).enable) 35 { 36 response->completionCode = IPMI_CC_PAYLOAD_TYPE_DISABLED; 37 return outPayload; 38 } 39 40 // Only one instance of SOL is currently supported. 41 if (request->payloadInstance != 1) 42 { 43 response->completionCode = IPMI_CC_INVALID_FIELD_REQUEST; 44 return outPayload; 45 } 46 47 auto session = (std::get<session::Manager&>(singletonPool).getSession( 48 handler.sessionID)).lock(); 49 50 if (!request->encryption && session->isCryptAlgoEnabled()) 51 { 52 response->completionCode = IPMI_CC_PAYLOAD_WITHOUT_ENCRYPTION; 53 return outPayload; 54 } 55 56 auto status = std::get<sol::Manager&>(singletonPool).isPayloadActive( 57 request->payloadInstance); 58 if (status) 59 { 60 response->completionCode = IPMI_CC_PAYLOAD_ALREADY_ACTIVE; 61 return outPayload; 62 } 63 64 // Set the current command's socket channel to the session 65 handler.setChannelInSession(); 66 67 // Start the SOL payload 68 try 69 { 70 std::get<sol::Manager&>(singletonPool).startPayloadInstance( 71 request->payloadInstance, 72 handler.sessionID); 73 } 74 catch (std::exception& e) 75 { 76 log<level::ERR>(e.what()); 77 response->completionCode = IPMI_CC_UNSPECIFIED_ERROR; 78 return outPayload; 79 } 80 81 response->inPayloadSize = endian::to_ipmi<uint16_t>(MAX_PAYLOAD_SIZE); 82 response->outPayloadSize = endian::to_ipmi<uint16_t>(MAX_PAYLOAD_SIZE); 83 response->portNum = endian::to_ipmi<uint16_t>(IPMI_STD_PORT); 84 85 // VLAN addressing is not used 86 response->vlanNum = 0xFFFF; 87 88 return outPayload; 89 } 90 91 std::vector<uint8_t> deactivatePayload(const std::vector<uint8_t>& inPayload, 92 const message::Handler& handler) 93 { 94 std::vector<uint8_t> outPayload(sizeof(DeactivatePayloadResponse)); 95 auto request = reinterpret_cast<const DeactivatePayloadRequest*> 96 (inPayload.data()); 97 auto response = reinterpret_cast<DeactivatePayloadResponse*> 98 (outPayload.data()); 99 100 response->completionCode = IPMI_CC_OK; 101 102 // SOL is the payload currently supported for deactivation 103 if (static_cast<uint8_t>(message::PayloadType::SOL) != request->payloadType) 104 { 105 response->completionCode = IPMI_CC_INVALID_FIELD_REQUEST; 106 return outPayload; 107 } 108 109 // Only one instance of SOL is supported 110 if (request->payloadInstance != 1) 111 { 112 response->completionCode = IPMI_CC_INVALID_FIELD_REQUEST; 113 return outPayload; 114 } 115 116 auto status = std::get<sol::Manager&>(singletonPool).isPayloadActive( 117 request->payloadInstance); 118 if (!status) 119 { 120 response->completionCode = IPMI_CC_PAYLOAD_DEACTIVATED; 121 return outPayload; 122 } 123 124 try 125 { 126 auto& context = std::get<sol::Manager&>(singletonPool).getContext 127 (request->payloadInstance); 128 auto sessionID = context.sessionID; 129 130 std::get<sol::Manager&>(singletonPool).stopPayloadInstance( 131 request->payloadInstance); 132 133 try 134 { 135 activating(request->payloadInstance, sessionID); 136 } 137 catch (std::exception& e) 138 { 139 log<level::INFO>(e.what()); 140 /* 141 * In case session has been closed (like in the case of inactivity 142 * timeout), then activating function would throw an exception, 143 * since sessionID is not found. IPMI success completion code is 144 * returned, since the session is closed. 145 */ 146 return outPayload; 147 } 148 149 auto check = std::get<session::Manager&>(singletonPool).stopSession 150 (sessionID); 151 if (!check) 152 { 153 response->completionCode = IPMI_CC_UNSPECIFIED_ERROR; 154 } 155 } 156 catch (std::exception& e) 157 { 158 log<level::ERR>(e.what()); 159 response->completionCode = IPMI_CC_UNSPECIFIED_ERROR; 160 return outPayload; 161 } 162 163 return outPayload; 164 } 165 166 std::vector<uint8_t> getPayloadStatus(const std::vector<uint8_t>& inPayload, 167 const message::Handler& handler) 168 { 169 std::vector<uint8_t> outPayload(sizeof(GetPayloadStatusResponse)); 170 auto request = reinterpret_cast<const GetPayloadStatusRequest*> 171 (inPayload.data()); 172 auto response = reinterpret_cast<GetPayloadStatusResponse*> 173 (outPayload.data()); 174 175 // SOL is the payload currently supported for payload status 176 if (static_cast<uint8_t>(message::PayloadType::SOL) != request->payloadType) 177 { 178 response->completionCode = IPMI_CC_UNSPECIFIED_ERROR; 179 return outPayload; 180 } 181 182 response->completionCode = IPMI_CC_OK; 183 response->capacity = MAX_PAYLOAD_INSTANCES; 184 185 // Currently we support only one SOL session 186 response->instance1 = 187 std::get<sol::Manager&>(singletonPool).isPayloadActive(1); 188 189 return outPayload; 190 } 191 192 std::vector<uint8_t> getPayloadInfo(const std::vector<uint8_t>& inPayload, 193 const message::Handler& handler) 194 { 195 std::vector<uint8_t> outPayload(sizeof(GetPayloadInfoResponse)); 196 auto request = reinterpret_cast<const GetPayloadInfoRequest*> 197 (inPayload.data()); 198 auto response = reinterpret_cast<GetPayloadInfoResponse*> 199 (outPayload.data()); 200 201 // SOL is the payload currently supported for payload status & only one 202 // instance of SOL is supported. 203 if (static_cast<uint8_t>(message::PayloadType::SOL) != request->payloadType 204 || request->payloadInstance != 1) 205 { 206 response->completionCode = IPMI_CC_INVALID_FIELD_REQUEST; 207 return outPayload; 208 } 209 210 auto status = std::get<sol::Manager&>(singletonPool).isPayloadActive( 211 request->payloadInstance); 212 213 if (!status) 214 { 215 response->completionCode = IPMI_CC_RESPONSE_ERROR; 216 return outPayload; 217 } 218 219 auto& context = std::get<sol::Manager&>(singletonPool).getContext 220 (request->payloadInstance); 221 response->sessionID = context.sessionID; 222 223 return outPayload; 224 } 225 226 } // namespace command 227 228 } // namespace sol 229