bridgingcommands:move get&send commands to new api
Rewrite get and send message commands to use new IPMI provider API.
Tested:
verified ipmitool get and send message command, is same both before and
after the changes
1. Enter in Manufacturing mode by executing below command
Command: ipmitool raw 0x30 0xB4 3 2
Response: //Success
2. Send message command
Command:
FS0:\cmdtool\> cmdtool.efi 20 18 34 06 2C D3 01 FC FC 04 00 2C FC 08
C1 13
Response: 00 00 00 00 00 00 //Success
3. Get message command
Commad:
FS0:\cmdtool\> cmdtool.efi 20 18 33
Response: 00 FC FC D4 30 2C FC 04 C1 13
Negative Test cases:
Send Message Command:
1. // Encryption Enabled
Command:
FS0:\cmdtool\> cmdtool.efi 20 18 34 26 2C D3 01 FC FC 04 00 2C FC 08 C1 13
Response: C9
2. // Authentication Enabled
Command:
FS0:\cmdtool\> cmdtool.efi 20 18 34 16 2C D3 01 FC FC 04 00 2C FC 08 C1 13
Response: C9
3. // Channel other than IPMB and Lan
Command:
FS0:\cmdtool\> cmdtool.efi 20 18 34 07 2C D3 01 FC FC 04 00 2C FC 08 C1 13
Response: C9
4. // IPMB data length Invalid:
Command:
FS0:\cmdtool\> cmdtool.efi 20 18 34 06 2C
Response: C7
5. // IPMB address invalid:
Command:
FS0:\cmdtool\> cmdtool.efi 20 18 34 06 2B D3 01 FC FC 04 00 2C FC 08 C1 13
Response: C9
6. // Tracking = 2 and 3 (Tracking mode not supported)
Command:
FS0:\cmdtool\> cmdtool.efi 20 18 34 86 2C D3 01 FC FC 04 00 2C FC 08 C1 13
Response: C9
Command:
FS0:\cmdtool\> cmdtool.efi 20 18 34 C6 2C D3 01 FC FC 04 00 2C FC 08 C1 13
Response: C9
7. // IPMB frame invalid:
Command:
FS0:\cmdtool\> cmdtool.efi 20 18 34 06 2C D3 01 FC FC 04 00 2C FC 08 C1 12
Response: C9
8. // Response queue max size: (After doing multiple send)
Command:
FS0:\cmdtool\> cmdtool.efi 20 18 34 06 2C D3 01 FC FC 04 00 2C FC 08 C1 13
Response: C0
9. IPMB layer non zero status:
Command:
FS0:\cmdtool\> cmdtool.efi 20 18 34 06 2C D4 00 FB FC 04 00 2C FC 09 C1 13
Response: CE
Get Message Command:
10. // After booting, do Get Message command (Before send command)
Command:
FS0:\cmdtool\> cmdtool.efi 20 18 33
Response: 80
Signed-off-by: jayaprakash Mutyala <mutyalax.jayaprakash@intel.com>
Signed-off-by: Deepak Kumar Sahu <deepakx.sahu@intel.com>
Change-Id: I2a4028dbe889a0737821f95889c39e44254a12ca
diff --git a/include/bridgingcommands.hpp b/include/bridgingcommands.hpp
index fe92f6c..6dbac02 100644
--- a/include/bridgingcommands.hpp
+++ b/include/bridgingcommands.hpp
@@ -100,12 +100,6 @@
constexpr uint8_t modeSendRaw = 0x2;
/**
- * @brief Command specific codes
- */
-constexpr ipmi_return_codes ipmiGetMessageCmdDataNotAvailable =
- static_cast<ipmi_return_codes>(0x80);
-
-/**
* @brief Ipmb frame
*/
typedef struct
@@ -182,54 +176,6 @@
};
/**
- * @brief Send Message Request
- */
-typedef struct
-{
- uint8_t channelData;
- uint8_t data[];
-
- constexpr uint8_t channelNumGet()
- {
- return (channelData & 0xF);
- }
-
- constexpr uint8_t authenticationGet()
- {
- return ((channelData & 0x10) >> 4);
- }
-
- constexpr uint8_t encryptionGet()
- {
- return ((channelData & 0x20) >> 5);
- }
-
- constexpr uint8_t modeGet()
- {
- return ((channelData & 0xC0) >> 6);
- }
-} __attribute__((packed)) sSendMessageReq;
-
-/**
- * @brief Get Message Response
- */
-typedef struct
-{
- uint8_t channelData;
- uint8_t data[];
-
- constexpr void channelNumSet(uint8_t num)
- {
- channelData |= num & 0xF;
- }
-
- constexpr void privilegeLvlSet(CommandPrivilege privLvl)
- {
- channelData |= static_cast<uint8_t>(privLvl) & 0xF0;
- }
-} __attribute__((packed)) sGetMessageRes;
-
-/**
* @brief Get Message Flags Response
*/
constexpr uint8_t getMsgFlagReceiveMessageBit = 0;
@@ -239,44 +185,6 @@
constexpr uint8_t getMsgFlagOEM1Bit = 6;
constexpr uint8_t getMsgFlagOEM2Bit = 7;
-/**
- * @brief Clear Message Flags Request
- */
-typedef struct
-{
- uint8_t flags;
-
- constexpr uint8_t receiveMessageBitGet()
- {
- return (flags & 0x1);
- }
-
- constexpr uint8_t eventMessageBitGet()
- {
- return ((flags & 0x2) >> 1);
- }
-
- constexpr uint8_t watchdogTimeoutBitGet()
- {
- return ((flags & 0x8) >> 3);
- }
-
- constexpr uint8_t oem0BitGet()
- {
- return ((flags & 0x20) >> 5);
- }
-
- constexpr uint8_t oem1BitGet()
- {
- return ((flags & 0x40) >> 6);
- }
-
- constexpr uint8_t oem2BitGet()
- {
- return ((flags & 0x80) >> 7);
- }
-} __attribute__((packed)) sClearMessageFlagsReq;
-
/** @class Bridging
*
* @brief Implement commands to support IPMI bridging.
@@ -287,26 +195,18 @@
Bridging() = default;
std::size_t getResponseQueueSize();
- std::vector<IpmbResponse> getResponseQueue();
void clearResponseQueue();
- ipmi_return_codes sendMessageHandler(ipmi_request_t request,
- ipmi_response_t response,
- ipmi_data_len_t dataLen);
+ ipmi::Cc handleIpmbChannel(const uint8_t tracking,
+ const std::vector<uint8_t> &msgData,
+ std::vector<uint8_t> &rspData);
- ipmi_return_codes getMessageHandler(ipmi_request_t request,
- ipmi_response_t response,
- ipmi_data_len_t dataLen);
- enum IpmiAppBridgingCmds
- {
- ipmiCmdGetMessage = 0x33,
- ipmiCmdSendMessage = 0x34,
- };
+ void insertMessageInQueue(IpmbResponse msg);
+
+ IpmbResponse getMessageFromQueue();
+
+ void eraseMessageFromQueue();
private:
std::vector<IpmbResponse> responseQueue;
-
- ipmi_return_codes handleIpmbChannel(sSendMessageReq *sendMsgReq,
- ipmi_response_t response,
- ipmi_data_len_t dataLen);
};
diff --git a/src/bridgingcommands.cpp b/src/bridgingcommands.cpp
index e21a738..0922438 100644
--- a/src/bridgingcommands.cpp
+++ b/src/bridgingcommands.cpp
@@ -49,7 +49,7 @@
/**
* @brief utils for checksum
*/
-static bool ipmbChecksumValidate(uint8_t *data, uint8_t length)
+static bool ipmbChecksumValidate(const uint8_t *data, uint8_t length)
{
if (data == nullptr)
{
@@ -89,21 +89,22 @@
return checksum;
}
-static inline bool ipmbConnectionHeaderChecksumValidate(ipmbHeader *ipmbHeader)
+static inline bool
+ ipmbConnectionHeaderChecksumValidate(const ipmbHeader *ipmbHeader)
{
- return ipmbChecksumValidate(reinterpret_cast<uint8_t *>(ipmbHeader),
+ return ipmbChecksumValidate(reinterpret_cast<const uint8_t *>(ipmbHeader),
ipmbConnectionHeaderLength);
}
-static inline bool ipmbDataChecksumValidate(ipmbHeader *ipmbHeader,
+static inline bool ipmbDataChecksumValidate(const ipmbHeader *ipmbHeader,
uint8_t length)
{
- return ipmbChecksumValidate(
- (reinterpret_cast<uint8_t *>(ipmbHeader) + ipmbConnectionHeaderLength),
- (length - ipmbConnectionHeaderLength));
+ return ipmbChecksumValidate((reinterpret_cast<const uint8_t *>(ipmbHeader) +
+ ipmbConnectionHeaderLength),
+ (length - ipmbConnectionHeaderLength));
}
-static bool isFrameValid(ipmbHeader *frame, uint8_t length)
+static bool isFrameValid(const ipmbHeader *frame, uint8_t length)
{
if ((length < ipmbMinFrameLength) || (length > ipmbMaxFrameLength))
{
@@ -237,21 +238,21 @@
}
}
-ipmi_return_codes Bridging::handleIpmbChannel(sSendMessageReq *sendMsgReq,
- ipmi_response_t response,
- ipmi_data_len_t dataLen)
+ipmi::Cc Bridging::handleIpmbChannel(const uint8_t tracking,
+ const std::vector<uint8_t> &msgData,
+ std::vector<uint8_t> &rspData)
{
ipmi::Manufacturing mtm;
- if ((*dataLen < (sizeof(sSendMessageReq) + ipmbMinFrameLength)) ||
- (*dataLen > (sizeof(sSendMessageReq) + ipmbMaxFrameLength)))
+ size_t msgLen = msgData.size();
+ if ((msgLen < ipmbMinFrameLength) || (msgLen > ipmbMaxFrameLength))
{
- *dataLen = 0;
- return IPMI_CC_REQ_DATA_LEN_INVALID;
+ phosphor::logging::log<phosphor::logging::level::INFO>(
+ "handleIpmbChannel, IPMB data length is invalid");
+ return ipmi::ccReqDataLenInvalid;
}
- auto sendMsgReqData = reinterpret_cast<ipmbHeader *>(sendMsgReq->data);
-
+ auto sendMsgReqData = reinterpret_cast<const ipmbHeader *>(msgData.data());
// TODO: check privilege lvl. Bridging to ME requires Administrator lvl
// allow bridging to ME only
@@ -259,8 +260,7 @@
{
phosphor::logging::log<phosphor::logging::level::INFO>(
"handleIpmbChannel, IPMB address invalid");
- *dataLen = 0;
- return IPMI_CC_PARM_OUT_OF_RANGE;
+ return ipmi::ccParmOutOfRange;
}
constexpr uint8_t shiftLUN = 2;
@@ -269,31 +269,28 @@
if (!isMeCmdAllowed((sendMsgReqData->Header.Req.rsNetFnLUN >> shiftLUN),
sendMsgReqData->Header.Req.cmd))
{
- return IPMI_CC_INSUFFICIENT_PRIVILEGE;
+ constexpr ipmi::Cc ccCmdNotSupportedInPresentState = 0xD5;
+ return ccCmdNotSupportedInPresentState;
}
}
// check allowed modes
- if (sendMsgReq->modeGet() != modeNoTracking &&
- sendMsgReq->modeGet() != modeTrackRequest)
+ if (tracking != modeNoTracking && tracking != modeTrackRequest)
{
phosphor::logging::log<phosphor::logging::level::INFO>(
"handleIpmbChannel, mode not supported");
- *dataLen = 0;
- return IPMI_CC_PARM_OUT_OF_RANGE;
+ return ipmi::ccParmOutOfRange;
}
// check if request contains valid IPMB frame
- if (!isFrameValid(sendMsgReqData, (*dataLen - sizeof(sSendMessageReq))))
+ if (!isFrameValid(sendMsgReqData, msgLen))
{
phosphor::logging::log<phosphor::logging::level::INFO>(
"handleIpmbChannel, IPMB frame invalid");
- *dataLen = 0;
- return IPMI_CC_PARM_OUT_OF_RANGE;
+ return ipmi::ccParmOutOfRange;
}
- auto ipmbRequest =
- IpmbRequest(sendMsgReqData, (*dataLen - sizeof(sSendMessageReq)));
+ auto ipmbRequest = IpmbRequest(sendMsgReqData, msgLen);
std::tuple<int, uint8_t, uint8_t, uint8_t, uint8_t, std::vector<uint8_t>>
ipmbResponse;
@@ -312,8 +309,7 @@
{
phosphor::logging::log<phosphor::logging::level::ERR>(
"handleIpmbChannel, dbus call exception");
- *dataLen = 0;
- return IPMI_CC_UNSPECIFIED_ERROR;
+ return ipmi::ccUnspecifiedError;
}
std::vector<uint8_t> dataReceived(0);
@@ -331,80 +327,108 @@
{
phosphor::logging::log<phosphor::logging::level::WARNING>(
"handleIpmbChannel, ipmb returned non zero status");
- *dataLen = 0;
- return IPMI_CC_RESPONSE_ERROR;
+ return ipmi::ccResponseError;
}
- auto sendMsgRes = reinterpret_cast<uint8_t *>(response);
-
- switch (sendMsgReq->modeGet())
+ switch (tracking)
{
case modeNoTracking:
- if (responseQueue.size() == responseQueueMaxSize)
+ {
+ if (getResponseQueueSize() == responseQueueMaxSize)
{
- *dataLen = 0;
- return IPMI_CC_BUSY;
+ return ipmi::ccBusy;
}
- responseQueue.insert(responseQueue.end(), std::move(respReceived));
- *dataLen = 0;
- return IPMI_CC_OK;
-
+ insertMessageInQueue(respReceived);
break;
+ }
case modeTrackRequest:
- respReceived.ipmbToi2cConstruct(sendMsgRes, dataLen);
- return IPMI_CC_OK;
-
+ {
+ size_t dataLength = 0;
+ respReceived.ipmbToi2cConstruct(rspData.data(), &dataLength);
+ // resizing the rspData to its correct length
+ rspData.resize(dataLength);
break;
+ }
default:
+ {
phosphor::logging::log<phosphor::logging::level::INFO>(
"handleIpmbChannel, mode not supported");
- *dataLen = 0;
- return IPMI_CC_PARM_OUT_OF_RANGE;
+ return ipmi::ccParmOutOfRange;
+ }
}
- *dataLen = 0;
- return IPMI_CC_UNSPECIFIED_ERROR;
+ return ipmi::ccSuccess;
}
-ipmi_return_codes Bridging::sendMessageHandler(ipmi_request_t request,
- ipmi_response_t response,
- ipmi_data_len_t dataLen)
+void Bridging::insertMessageInQueue(IpmbResponse msg)
{
- ipmi_return_codes retCode = IPMI_CC_OK;
+ responseQueue.insert(responseQueue.end(), std::move(msg));
+}
- if (*dataLen < sizeof(sSendMessageReq))
- {
- *dataLen = 0;
- return IPMI_CC_REQ_DATA_LEN_INVALID;
- }
+void Bridging::eraseMessageFromQueue()
+{
+ responseQueue.erase(responseQueue.begin());
+}
- auto sendMsgReq = reinterpret_cast<sSendMessageReq *>(request);
+IpmbResponse Bridging::getMessageFromQueue()
+{
+ return responseQueue.front();
+}
+/**
+ * @brief This command is used for bridging ipmi message between channels.
+ * @param channelNumber - channel number to send message to
+ * @param authenticationEnabled - authentication.
+ * @param encryptionEnabled - encryption
+ * @param Tracking - track request
+ * @param msg - message data
+ *
+ * @return IPMI completion code plus response data on success.
+ * - rspData - response data
+ **/
+ipmi::RspType<std::vector<uint8_t> // responseData
+ >
+ ipmiAppSendMessage(const uint4_t channelNumber,
+ const bool authenticationEnabled,
+ const bool encryptionEnabled, const uint2_t tracking,
+ ipmi::message::Payload &msg)
+{
// check message fields:
// encryption not supported
- if (sendMsgReq->encryptionGet() != 0)
+ if (encryptionEnabled)
{
phosphor::logging::log<phosphor::logging::level::INFO>(
- "sendMessageHandler, encryption not supported");
- *dataLen = 0;
- return IPMI_CC_PARM_OUT_OF_RANGE;
+ "ipmiAppSendMessage, encryption not supported");
+ return ipmi::responseParmOutOfRange();
}
// authentication not supported
- if (sendMsgReq->authenticationGet() != 0)
+ if (authenticationEnabled)
{
phosphor::logging::log<phosphor::logging::level::INFO>(
- "sendMessageHandler, authentication not supported");
- *dataLen = 0;
- return IPMI_CC_PARM_OUT_OF_RANGE;
+ "ipmiAppSendMessage, authentication not supported");
+ return ipmi::responseParmOutOfRange();
}
- switch (sendMsgReq->channelNumGet())
+ ipmi::Cc returnVal;
+ std::vector<uint8_t> rspData(ipmbMaxFrameLength);
+ size_t dataLength = 0;
+ std::vector<uint8_t> unpackMsg;
+
+ auto channelNo = static_cast<const uint8_t>(channelNumber);
+ // Get the channel number
+ switch (channelNo)
{
// we only handle ipmb for now
case targetChannelIpmb:
case targetChannelOtherLan:
- retCode = handleIpmbChannel(sendMsgReq, response, dataLen);
+ if (msg.unpack(unpackMsg) || !msg.fullyUnpacked())
+ {
+ return ipmi::responseReqDataLenInvalid();
+ }
+
+ returnVal = bridging.handleIpmbChannel(
+ static_cast<const uint8_t>(tracking), unpackMsg, rspData);
break;
// fall through to default
case targetChannelIcmb10:
@@ -417,69 +441,62 @@
case targetChannelSystemInterface:
default:
phosphor::logging::log<phosphor::logging::level::INFO>(
- "sendMessageHandler, TargetChannel invalid");
- *dataLen = 0;
- return IPMI_CC_PARM_OUT_OF_RANGE;
+ "ipmiAppSendMessage, TargetChannel invalid");
+ return ipmi::responseParmOutOfRange();
+ }
+ if (returnVal != ipmi::ccSuccess)
+ {
+ return ipmi::response(returnVal);
}
- return retCode;
+ return ipmi::responseSuccess(rspData);
}
-ipmi_return_codes Bridging::getMessageHandler(ipmi_request_t request,
- ipmi_response_t response,
- ipmi_data_len_t dataLen)
+/**
+ * @brief This command is used to Get data from the receive message queue.
+ * This command should be executed executed via system interface only.
+ *
+ * @return IPMI completion code plus response data on success.
+ * - channelNumber
+ * - messageData
+ **/
+
+ipmi::RspType<uint8_t, // channelNumber
+ std::vector<uint8_t> // messageData
+ >
+ ipmiAppGetMessage()
{
- if (*dataLen != 0)
+ uint8_t channelData = 0;
+ std::vector<uint8_t> res(ipmbMaxFrameLength);
+ size_t dataLength = 0;
+
+ if (!bridging.getResponseQueueSize())
{
- *dataLen = 0;
- return IPMI_CC_REQ_DATA_LEN_INVALID;
- }
-
- auto getMsgRes = reinterpret_cast<sGetMessageRes *>(response);
- auto getMsgResData = static_cast<uint8_t *>(getMsgRes->data);
-
- std::memset(getMsgRes, 0, sizeof(sGetMessageRes));
-
- auto respQueueItem = responseQueue.begin();
-
- if (respQueueItem == responseQueue.end())
- {
+ constexpr ipmi::Cc ipmiGetMessageCmdDataNotAvailable = 0x80;
phosphor::logging::log<phosphor::logging::level::INFO>(
- "getMessageHandler, no data available");
- *dataLen = 0;
- return ipmiGetMessageCmdDataNotAvailable;
+ "ipmiAppGetMessage, no data available");
+ return ipmi::response(ipmiGetMessageCmdDataNotAvailable);
}
- // set message fields
- getMsgRes->privilegeLvlSet(SYSTEM_INTERFACE);
- getMsgRes->channelNumSet(targetChannelSystemInterface);
+ // channel number set.
+ channelData |= static_cast<uint8_t>(targetChannelSystemInterface) & 0x0F;
- // construct response
- respQueueItem->ipmbToi2cConstruct(getMsgResData, dataLen);
- responseQueue.erase(respQueueItem);
+ // Priviledge level set.
+ channelData |= SYSTEM_INTERFACE & 0xF0;
- *dataLen = *dataLen + sizeof(sGetMessageRes);
- return IPMI_CC_OK;
-}
+ // Get the first message from queue
+ auto respQueueItem = bridging.getMessageFromQueue();
-ipmi_ret_t ipmiAppSendMessage(ipmi_netfn_t netFn, ipmi_cmd_t cmd,
- ipmi_request_t request, ipmi_response_t response,
- ipmi_data_len_t dataLen, ipmi_context_t context)
-{
- ipmi_ret_t retCode = IPMI_CC_OK;
- retCode = bridging.sendMessageHandler(request, response, dataLen);
+ // construct response data.
+ respQueueItem.ipmbToi2cConstruct(res.data(), &dataLength);
- return retCode;
-}
+ // Remove the message from queue
+ bridging.eraseMessageFromQueue();
-ipmi_ret_t ipmiAppGetMessage(ipmi_netfn_t netFn, ipmi_cmd_t cmd,
- ipmi_request_t request, ipmi_response_t response,
- ipmi_data_len_t dataLen, ipmi_context_t context)
-{
- ipmi_ret_t retCode = IPMI_CC_OK;
- retCode = bridging.getMessageHandler(request, response, dataLen);
+ // resizing the rspData to its correct length
+ res.resize(dataLength);
- return retCode;
+ return ipmi::responseSuccess(channelData, res);
}
std::size_t Bridging::getResponseQueueSize()
@@ -654,13 +671,13 @@
ipmi::app::cmdGetMessageFlags, ipmi::Privilege::User,
ipmiAppGetMessageFlags);
- ipmi_register_callback(NETFUN_APP,
- Bridging::IpmiAppBridgingCmds::ipmiCmdGetMessage,
- NULL, ipmiAppGetMessage, PRIVILEGE_USER);
+ ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnApp,
+ ipmi::app::cmdGetMessage, ipmi::Privilege::User,
+ ipmiAppGetMessage);
- ipmi_register_callback(NETFUN_APP,
- Bridging::IpmiAppBridgingCmds::ipmiCmdSendMessage,
- NULL, ipmiAppSendMessage, PRIVILEGE_USER);
+ ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnApp,
+ ipmi::app::cmdSendMessage, ipmi::Privilege::User,
+ ipmiAppSendMessage);
ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnApp,
ipmi::app::cmdReadEventMessageBuffer,