blob: 3b5b4f8abc7954b00b1372481118c4435425a7f5 [file] [log] [blame]
#include "payload_cmds.hpp"
#include "main.hpp"
#include "sol/sol_manager.hpp"
#include "sol_cmds.hpp"
#include <ipmid/api.h>
#include <phosphor-logging/log.hpp>
namespace sol
{
namespace command
{
using namespace phosphor::logging;
std::vector<uint8_t> activatePayload(const std::vector<uint8_t>& inPayload,
const message::Handler& handler)
{
std::vector<uint8_t> outPayload(sizeof(ActivatePayloadResponse));
auto request =
reinterpret_cast<const ActivatePayloadRequest*>(inPayload.data());
auto response =
reinterpret_cast<ActivatePayloadResponse*>(outPayload.data());
response->completionCode = IPMI_CC_OK;
// SOL is the payload currently supported for activation.
if (static_cast<uint8_t>(message::PayloadType::SOL) != request->payloadType)
{
response->completionCode = IPMI_CC_INVALID_FIELD_REQUEST;
return outPayload;
}
if (!std::get<sol::Manager&>(singletonPool).enable)
{
response->completionCode = IPMI_CC_PAYLOAD_TYPE_DISABLED;
return outPayload;
}
// Only one instance of SOL is currently supported.
if (request->payloadInstance != 1)
{
response->completionCode = IPMI_CC_INVALID_FIELD_REQUEST;
return outPayload;
}
auto session = std::get<session::Manager&>(singletonPool)
.getSession(handler.sessionID);
if (!request->encryption && session->isCryptAlgoEnabled())
{
response->completionCode = IPMI_CC_PAYLOAD_WITHOUT_ENCRYPTION;
return outPayload;
}
auto status = std::get<sol::Manager&>(singletonPool)
.isPayloadActive(request->payloadInstance);
if (status)
{
response->completionCode = IPMI_CC_PAYLOAD_ALREADY_ACTIVE;
return outPayload;
}
// Set the current command's socket channel to the session
handler.setChannelInSession();
// Start the SOL payload
try
{
std::get<sol::Manager&>(singletonPool)
.startPayloadInstance(request->payloadInstance, handler.sessionID);
}
catch (std::exception& e)
{
log<level::ERR>(e.what());
response->completionCode = IPMI_CC_UNSPECIFIED_ERROR;
return outPayload;
}
response->inPayloadSize = endian::to_ipmi<uint16_t>(MAX_PAYLOAD_SIZE);
response->outPayloadSize = endian::to_ipmi<uint16_t>(MAX_PAYLOAD_SIZE);
response->portNum = endian::to_ipmi<uint16_t>(IPMI_STD_PORT);
// VLAN addressing is not used
response->vlanNum = 0xFFFF;
return outPayload;
}
std::vector<uint8_t> deactivatePayload(const std::vector<uint8_t>& inPayload,
const message::Handler& handler)
{
std::vector<uint8_t> outPayload(sizeof(DeactivatePayloadResponse));
auto request =
reinterpret_cast<const DeactivatePayloadRequest*>(inPayload.data());
auto response =
reinterpret_cast<DeactivatePayloadResponse*>(outPayload.data());
response->completionCode = IPMI_CC_OK;
// SOL is the payload currently supported for deactivation
if (static_cast<uint8_t>(message::PayloadType::SOL) != request->payloadType)
{
response->completionCode = IPMI_CC_INVALID_FIELD_REQUEST;
return outPayload;
}
// Only one instance of SOL is supported
if (request->payloadInstance != 1)
{
response->completionCode = IPMI_CC_INVALID_FIELD_REQUEST;
return outPayload;
}
auto status = std::get<sol::Manager&>(singletonPool)
.isPayloadActive(request->payloadInstance);
if (!status)
{
response->completionCode = IPMI_CC_PAYLOAD_DEACTIVATED;
return outPayload;
}
try
{
auto& context = std::get<sol::Manager&>(singletonPool)
.getContext(request->payloadInstance);
auto sessionID = context.sessionID;
std::get<sol::Manager&>(singletonPool)
.stopPayloadInstance(request->payloadInstance);
try
{
activating(request->payloadInstance, sessionID);
}
catch (std::exception& e)
{
log<level::INFO>(e.what());
/*
* In case session has been closed (like in the case of inactivity
* timeout), then activating function would throw an exception,
* since sessionID is not found. IPMI success completion code is
* returned, since the session is closed.
*/
return outPayload;
}
auto check =
std::get<session::Manager&>(singletonPool).stopSession(sessionID);
if (!check)
{
response->completionCode = IPMI_CC_UNSPECIFIED_ERROR;
}
}
catch (std::exception& e)
{
log<level::ERR>(e.what());
response->completionCode = IPMI_CC_UNSPECIFIED_ERROR;
return outPayload;
}
return outPayload;
}
std::vector<uint8_t> getPayloadStatus(const std::vector<uint8_t>& inPayload,
const message::Handler& handler)
{
std::vector<uint8_t> outPayload(sizeof(GetPayloadStatusResponse));
auto request =
reinterpret_cast<const GetPayloadStatusRequest*>(inPayload.data());
auto response =
reinterpret_cast<GetPayloadStatusResponse*>(outPayload.data());
// SOL is the payload currently supported for payload status
if (static_cast<uint8_t>(message::PayloadType::SOL) != request->payloadType)
{
response->completionCode = IPMI_CC_UNSPECIFIED_ERROR;
return outPayload;
}
response->completionCode = IPMI_CC_OK;
response->capacity = MAX_PAYLOAD_INSTANCES;
// Currently we support only one SOL session
response->instance1 =
std::get<sol::Manager&>(singletonPool).isPayloadActive(1);
return outPayload;
}
std::vector<uint8_t> getPayloadInfo(const std::vector<uint8_t>& inPayload,
const message::Handler& handler)
{
std::vector<uint8_t> outPayload(sizeof(GetPayloadInfoResponse));
auto request =
reinterpret_cast<const GetPayloadInfoRequest*>(inPayload.data());
auto response =
reinterpret_cast<GetPayloadInfoResponse*>(outPayload.data());
// SOL is the payload currently supported for payload status & only one
// instance of SOL is supported.
if (static_cast<uint8_t>(message::PayloadType::SOL) !=
request->payloadType ||
request->payloadInstance != 1)
{
response->completionCode = IPMI_CC_INVALID_FIELD_REQUEST;
return outPayload;
}
auto status = std::get<sol::Manager&>(singletonPool)
.isPayloadActive(request->payloadInstance);
if (status)
{
auto& context = std::get<sol::Manager&>(singletonPool)
.getContext(request->payloadInstance);
response->sessionID = context.sessionID;
}
else
{
// No active payload - return session id as 0
response->sessionID = 0;
}
response->completionCode = IPMI_CC_OK;
return outPayload;
}
} // namespace command
} // namespace sol