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