Add command handler for Activate payload command.
Change-Id: I95d2d82409dabde7139871c7d62d5b5106c1c4d8
Signed-off-by: Tom Joseph <tomjoseph@in.ibm.com>
diff --git a/Makefile.am b/Makefile.am
index ad42d8d..cd4682e 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -48,7 +48,9 @@
sol/sol_manager.cpp \
sol/sol_context.cpp \
command/sol_cmds.hpp \
- command/sol_cmds.cpp
+ command/sol_cmds.cpp \
+ command/payload_cmds.hpp \
+ command/payload_cmds.cpp
netipmid_CPPFLAGS = -DNET_IPMID_LIB_PATH=\"/usr/lib/net-ipmid/\"
netipmid_LDFLAGS = $(SYSTEMD_LIBS) $(CRYPTO_LIBS) $(libmapper_LIBS) $(PHOSPHOR_LOGGING_LIBS) $(LIBADD_DLOPEN) -export-dynamic
diff --git a/command/payload_cmds.cpp b/command/payload_cmds.cpp
new file mode 100644
index 0000000..02c854a
--- /dev/null
+++ b/command/payload_cmds.cpp
@@ -0,0 +1,86 @@
+#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(std::vector<uint8_t>& inPayload,
+ const message::Handler& handler)
+{
+ std::vector<uint8_t> outPayload(sizeof(ActivatePayloadResponse));
+ auto request = reinterpret_cast<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;
+ }
+
+ // 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;
+}
+
+} // namespace command
+
+} // namespace sol
diff --git a/command/payload_cmds.hpp b/command/payload_cmds.hpp
new file mode 100644
index 0000000..ed6ca92
--- /dev/null
+++ b/command/payload_cmds.hpp
@@ -0,0 +1,116 @@
+#pragma once
+
+#include <vector>
+#include "message_handler.hpp"
+
+namespace sol
+{
+
+namespace command
+{
+
+constexpr uint8_t IPMI_CC_PAYLOAD_ALREADY_ACTIVE = 0x80;
+constexpr uint8_t IPMI_CC_PAYLOAD_TYPE_DISABLED = 0x81;
+constexpr uint8_t IPMI_CC_PAYLOAD_ACTIVATION_LIMIT = 0x82;
+constexpr uint8_t IPMI_CC_PAYLOAD_WITH_ENCRYPTION = 0x83;
+constexpr uint8_t IPMI_CC_PAYLOAD_WITHOUT_ENCRYPTION = 0x84;
+
+/** @struct ActivatePayloadRequest
+ *
+ * IPMI payload for Activate Payload command request.
+ */
+struct ActivatePayloadRequest
+{
+#if BYTE_ORDER == LITTLE_ENDIAN
+ uint8_t payloadType : 6; //!< Payload type.
+ uint8_t reserved1 : 2; //!< Reserved.
+#endif
+
+#if BYTE_ORDER == BIG_ENDIAN
+ uint8_t reserved1 : 2; //!< Payload type.
+ uint8_t payloadType : 6; //!< Payload type.
+#endif
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+ uint8_t payloadInstance : 4; //!< Payload instance.
+ uint8_t reserved2 : 4; //!< Reserved.
+#endif
+
+#if BYTE_ORDER == BIG_ENDIAN
+ uint8_t reserved2 : 4; //!< Reserved.
+ uint8_t payloadInstance : 4; //!< Payload instance.
+#endif
+
+ /** @brief The following Auxiliary Request Data applies only for payload
+ * SOL only.
+ */
+#if BYTE_ORDER == LITTLE_ENDIAN
+ uint8_t reserved4 : 1; //!< Reserved.
+ uint8_t handshake : 1; //!< SOL startup handshake.
+ uint8_t alert : 2; //!< Shared serial alert behavior.
+ uint8_t reserved3 : 1; //!< Reserved.
+ uint8_t testMode : 1; //!< Test mode.
+ uint8_t auth : 1; //!< If true, activate payload with authentication.
+ uint8_t encryption : 1; //!< If true, activate payload with encryption.
+#endif
+
+#if BYTE_ORDER == BIG_ENDIAN
+ uint8_t encryption : 1; //!< If true, activate payload with encryption.
+ uint8_t auth : 1; //!< If true, activate payload with authentication.
+ uint8_t testMode : 1; //!< Test mode.
+ uint8_t reserved3 : 1; //!< Reserved.
+ uint8_t alert : 2; //!< Shared serial alert behavior.
+ uint8_t handshake : 1; //!< SOL startup handshake.
+ uint8_t reserved4 : 1; //!< Reserved.
+#endif
+
+ uint8_t reserved5; //!< Reserved.
+ uint8_t reserved6; //!< Reserved.
+ uint8_t reserved7; //!< Reserved.
+} __attribute__((packed));
+
+/** @struct ActivatePayloadResponse
+ *
+ * IPMI payload for Activate Payload command response.
+ */
+struct ActivatePayloadResponse
+{
+ uint8_t completionCode; //!< Completion code.
+ uint8_t reserved1; //!< Reserved.
+ uint8_t reserved2; //!< Reserved.
+ uint8_t reserved3; //!< Reserved.
+
+ // Test Mode
+#if BYTE_ORDER == LITTLE_ENDIAN
+ uint8_t testMode : 1; //!< Test mode.
+ uint8_t reserved4 : 7; //!< Reserved.
+#endif
+
+#if BYTE_ORDER == BIG_ENDIAN
+ uint8_t reserved4 : 7; //!< Reserved.
+ uint8_t testMode : 1; //!< Test mode.
+#endif
+
+ uint16_t inPayloadSize; //!< Inbound payload size
+ uint16_t outPayloadSize; //!< Outbound payload size.
+ uint16_t portNum; //!< Payload UDP port number.
+ uint16_t vlanNum; //!< Payload VLAN number.
+} __attribute__((packed));
+
+/** @brief Activate Payload Command.
+ *
+ * This command is used for activating and deactivating a payload type under a
+ * given IPMI session. The UDP Port number for SOL is the same as the port that
+ * was used to establish the IPMI session.
+ *
+ * @param[in] inPayload - Request data for the command.
+ * @param[in] handler - Reference to the message handler.
+ *
+ * @return Response data for the command
+ */
+std::vector<uint8_t> activatePayload(std::vector<uint8_t>& inPayload,
+ const message::Handler& handler);
+
+} // namespace command
+
+} // namespace sol