blob: 0cc52cc1713ee5bcda1caefa05bce8c167166b04 [file] [log] [blame]
#include <host-ipmid/ipmid-api.h>
#include <phosphor-logging/log.hpp>
#include "main.hpp"
#include "payload_cmds.hpp"
#include "sol/sol_manager.hpp"
#include "sol_cmds.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)).lock();
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;
}
} // namespace command
} // namespace sol