storagecommands: move Read and Write FRU data
Rewrite "Read and write FRU data" to new IPMI provider API.
Tested:
verified using ipmitool storage commands.
a. read fru data
b. write fru data before and after the changes.
Write Fru data:
Input Command: ipmitool raw 0x0a 0x12 0x00 0x02 0x01 0x15 0x26 0x24
0x20 0x1a 0x10 0x01 0x02 0x03 0x5 0x43 0x55 0x66 0xaa 0xbb 0xaa
Output: 00
Read fru data:
Input Command: ipmitool raw 0x0a 0x11 0x00 0x02 0x01 0x10
Output: 10 15 26 24 20 1a 10 01 02 03 05 43 55 66 aa bb aa
Signed-off-by: jayaprakash Mutyala <mutyalax.jayaprakash@intel.com>
Change-Id: Id9e52623d262bab8fa1fe861896fc36a43c9f488
diff --git a/include/storagecommands.hpp b/include/storagecommands.hpp
index 1c709d1..c42f158 100644
--- a/include/storagecommands.hpp
+++ b/include/storagecommands.hpp
@@ -56,22 +56,6 @@
overflow = 0x80
};
-#pragma pack(push, 1)
-struct GetFRUAreaReq
-{
- uint8_t fruDeviceID;
- uint16_t fruInventoryOffset;
- uint8_t countToRead;
-};
-
-struct WriteFRUDataReq
-{
- uint8_t fruDeviceID;
- uint16_t fruInventoryOffset;
- uint8_t data[];
-};
-#pragma pack(pop)
-
enum class GetFRUAreaAccessType : uint8_t
{
byte = 0x0,
@@ -90,8 +74,6 @@
enum class IPMINetfnStorageCmds : ipmi_cmd_t
{
- ipmiCmdReadFRUData = 0x11,
- ipmiCmdWriteFRUData = 0x12,
ipmiCmdGetRepositoryInfo = 0x20,
ipmiCmdGetSDRAllocationInfo = 0x21,
ipmiCmdReserveSDR = 0x22,
diff --git a/src/storagecommands.cpp b/src/storagecommands.cpp
index 1db2f0d..b35ae9b 100644
--- a/src/storagecommands.cpp
+++ b/src/storagecommands.cpp
@@ -261,96 +261,92 @@
return IPMI_CC_OK;
}
-ipmi_ret_t ipmiStorageReadFRUData(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)
+/** @brief implements the read FRU data command
+ * @param fruDeviceId - FRU Device ID
+ * @param fruInventoryOffset - FRU Inventory Offset to write
+ * @param countToRead - Count to read
+ *
+ * @returns ipmi completion code plus response data
+ * - countWritten - Count written
+ */
+ipmi::RspType<uint8_t, // Count
+ std::vector<uint8_t> // Requested data
+ >
+ ipmiStorageReadFruData(uint8_t fruDeviceId, uint16_t fruInventoryOffset,
+ uint8_t countToRead)
{
- if (*dataLen != 4)
+ if (fruDeviceId == 0xFF)
{
- *dataLen = 0;
- return IPMI_CC_REQ_DATA_LEN_INVALID;
- }
- *dataLen = 0; // default to 0 in case of an error
-
- auto req = static_cast<GetFRUAreaReq*>(request);
-
- if (req->countToRead > maxMessageSize - 1)
- {
- return IPMI_CC_INVALID_FIELD_REQUEST;
- }
- ipmi_ret_t status = replaceCacheFru(req->fruDeviceID);
-
- if (status != IPMI_CC_OK)
- {
- return status;
+ return ipmi::responseInvalidFieldRequest();
}
- size_t fromFRUByteLen = 0;
- if (req->countToRead + req->fruInventoryOffset < fruCache.size())
- {
- fromFRUByteLen = req->countToRead;
- }
- else if (fruCache.size() > req->fruInventoryOffset)
- {
- fromFRUByteLen = fruCache.size() - req->fruInventoryOffset;
- }
- size_t padByteLen = req->countToRead - fromFRUByteLen;
- uint8_t* respPtr = static_cast<uint8_t*>(response);
- *respPtr = req->countToRead;
- std::copy(fruCache.begin() + req->fruInventoryOffset,
- fruCache.begin() + req->fruInventoryOffset + fromFRUByteLen,
- ++respPtr);
- // if longer than the fru is requested, fill with 0xFF
- if (padByteLen)
- {
- respPtr += fromFRUByteLen;
- std::fill(respPtr, respPtr + padByteLen, 0xFF);
- }
- *dataLen = fromFRUByteLen + 1;
+ ipmi::Cc status = replaceCacheFru(fruDeviceId);
- return IPMI_CC_OK;
+ if (status != ipmi::ccSuccess)
+ {
+ return ipmi::response(status);
+ }
+
+ size_t fromFruByteLen = 0;
+ if (countToRead + fruInventoryOffset < fruCache.size())
+ {
+ fromFruByteLen = countToRead;
+ }
+ else if (fruCache.size() > fruInventoryOffset)
+ {
+ fromFruByteLen = fruCache.size() - fruInventoryOffset;
+ }
+ else
+ {
+ return ipmi::responseInvalidFieldRequest();
+ }
+
+ std::vector<uint8_t> requestedData;
+
+ requestedData.insert(
+ requestedData.begin(), fruCache.begin() + fruInventoryOffset,
+ fruCache.begin() + fruInventoryOffset + fromFruByteLen);
+
+ return ipmi::responseSuccess(countToRead, requestedData);
}
-ipmi_ret_t ipmiStorageWriteFRUData(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)
+/** @brief implements the write FRU data command
+ * @param fruDeviceId - FRU Device ID
+ * @param fruInventoryOffset - FRU Inventory Offset to write
+ * @param dataToWrite - Data to write
+ *
+ * @returns ipmi completion code plus response data
+ * - countWritten - Count written
+ */
+ipmi::RspType<uint8_t>
+ ipmiStorageWriteFruData(uint8_t fruDeviceId, uint16_t fruInventoryOffset,
+ std::vector<uint8_t>& dataToWrite)
{
- if (*dataLen < 4 ||
- *dataLen >=
- 0xFF + 3) // count written return is one byte, so limit to one byte
- // of data after the three request data bytes
+ if (fruDeviceId == 0xFF)
{
- *dataLen = 0;
- return IPMI_CC_REQ_DATA_LEN_INVALID;
+ return ipmi::responseInvalidFieldRequest();
}
- auto req = static_cast<WriteFRUDataReq*>(request);
- size_t writeLen = *dataLen - 3;
- *dataLen = 0; // default to 0 in case of an error
+ size_t writeLen = dataToWrite.size();
- ipmi_ret_t status = replaceCacheFru(req->fruDeviceID);
- if (status != IPMI_CC_OK)
+ ipmi::Cc status = replaceCacheFru(fruDeviceId);
+ if (status != ipmi::ccSuccess)
{
- return status;
+ return ipmi::response(status);
}
- int lastWriteAddr = req->fruInventoryOffset + writeLen;
+ int lastWriteAddr = fruInventoryOffset + writeLen;
if (fruCache.size() < lastWriteAddr)
{
- fruCache.resize(req->fruInventoryOffset + writeLen);
+ fruCache.resize(fruInventoryOffset + writeLen);
}
- std::copy(req->data, req->data + writeLen,
- fruCache.begin() + req->fruInventoryOffset);
+ std::copy(dataToWrite.begin(), dataToWrite.begin() + writeLen,
+ fruCache.begin() + fruInventoryOffset);
bool atEnd = false;
if (fruCache.size() >= sizeof(FRUHeader))
{
-
FRUHeader* header = reinterpret_cast<FRUHeader*>(fruCache.data());
int lastRecordStart = std::max(
@@ -374,16 +370,16 @@
}
}
}
- uint8_t* respPtr = static_cast<uint8_t*>(response);
+ uint8_t countWritten = 0;
if (atEnd)
{
// cancel timer, we're at the end so might as well send it
cacheTimer->stop();
if (!writeFru())
{
- return IPMI_CC_INVALID_FIELD_REQUEST;
+ return ipmi::responseInvalidFieldRequest();
}
- *respPtr = std::min(fruCache.size(), static_cast<size_t>(0xFF));
+ countWritten = std::min(fruCache.size(), static_cast<size_t>(0xFF));
}
else
{
@@ -392,12 +388,10 @@
createTimer();
cacheTimer->start(std::chrono::duration_cast<std::chrono::microseconds>(
std::chrono::seconds(cacheTimeoutSeconds)));
- *respPtr = 0;
+ countWritten = 0;
}
- *dataLen = 1;
-
- return IPMI_CC_OK;
+ return ipmi::responseSuccess(countWritten);
}
/** @brief implements the get FRU inventory area info command
@@ -1085,16 +1079,14 @@
ipmi::storage::cmdGetFruInventoryAreaInfo,
ipmi::Privilege::User, ipmiStorageGetFruInvAreaInfo);
// <READ FRU Data>
- ipmiPrintAndRegister(
- NETFUN_STORAGE,
- static_cast<ipmi_cmd_t>(IPMINetfnStorageCmds::ipmiCmdReadFRUData), NULL,
- ipmiStorageReadFRUData, PRIVILEGE_USER);
+ ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnStorage,
+ ipmi::storage::cmdReadFruData, ipmi::Privilege::User,
+ ipmiStorageReadFruData);
// <WRITE FRU Data>
- ipmiPrintAndRegister(
- NETFUN_STORAGE,
- static_cast<ipmi_cmd_t>(IPMINetfnStorageCmds::ipmiCmdWriteFRUData),
- NULL, ipmiStorageWriteFRUData, PRIVILEGE_OPERATOR);
+ ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnStorage,
+ ipmi::storage::cmdWriteFruData,
+ ipmi::Privilege::Operator, ipmiStorageWriteFruData);
// <Get SEL Info>
ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnStorage,