libpldmresponder: Implement GetFRURecordByOption
Implement handler for GetFRURecordByOption command
Signed-off-by: John Wang <wangzqbj@inspur.com>
Change-Id: If2bc90872b2521f1771aa800de6fbce569a5b339
diff --git a/libpldmresponder/fru.cpp b/libpldmresponder/fru.cpp
index ce470ab..cb7d5f7 100644
--- a/libpldmresponder/fru.cpp
+++ b/libpldmresponder/fru.cpp
@@ -204,6 +204,42 @@
iter);
}
+int FruImpl::getFRURecordByOption(std::vector<uint8_t>& fruData,
+ uint16_t /* fruTableHandle */,
+ uint16_t recordSetIdentifer,
+ uint8_t recordType, uint8_t fieldType)
+{
+ // FRU table is built lazily, build if not done.
+ buildFRUTable();
+
+ /* 7 is sizeof(checksum,4) + padBytesMax(3)
+ * We can not know size of the record table got by options in advance, but
+ * it must be less than the source table. So it's safe to use sizeof the
+ * source table + 7 as the buffer length
+ */
+ size_t recordTableSize = table.size() - padBytes + 7;
+ fruData.resize(recordTableSize, 0);
+
+ get_fru_record_by_option(table.data(), table.size() - padBytes,
+ fruData.data(), &recordTableSize,
+ recordSetIdentifer, recordType, fieldType);
+
+ if (recordTableSize == 0)
+ {
+ return PLDM_FRU_DATA_STRUCTURE_TABLE_UNAVAILABLE;
+ }
+
+ auto pads = utils::getNumPadBytes(recordTableSize);
+ auto sum = crc32(fruData.data(), recordTableSize + pads);
+
+ auto iter = fruData.begin() + recordTableSize + pads;
+ std::copy_n(reinterpret_cast<const uint8_t*>(&checksum), sizeof(checksum),
+ iter);
+ fruData.resize(recordTableSize + pads + sizeof(sum));
+
+ return PLDM_SUCCESS;
+}
+
namespace fru
{
@@ -262,6 +298,57 @@
return response;
}
+Response Handler::getFRURecordByOption(const pldm_msg* request,
+ size_t payloadLength)
+{
+ if (payloadLength != sizeof(pldm_get_fru_record_by_option_req))
+ {
+ return ccOnlyResponse(request, PLDM_ERROR_INVALID_LENGTH);
+ }
+
+ uint32_t retDataTransferHandle{};
+ uint16_t retFruTableHandle{};
+ uint16_t retRecordSetIdentifier{};
+ uint8_t retRecordType{};
+ uint8_t retFieldType{};
+ uint8_t retTransferOpFlag{};
+
+ auto rc = decode_get_fru_record_by_option_req(
+ request, payloadLength, &retDataTransferHandle, &retFruTableHandle,
+ &retRecordSetIdentifier, &retRecordType, &retFieldType,
+ &retTransferOpFlag);
+
+ if (rc != PLDM_SUCCESS)
+ {
+ return ccOnlyResponse(request, rc);
+ }
+
+ std::vector<uint8_t> fruData;
+ rc = impl.getFRURecordByOption(fruData, retFruTableHandle,
+ retRecordSetIdentifier, retRecordType,
+ retFieldType);
+ if (rc != PLDM_SUCCESS)
+ {
+ return ccOnlyResponse(request, rc);
+ }
+
+ auto respPayloadLength =
+ PLDM_GET_FRU_RECORD_BY_OPTION_MIN_RESP_BYTES + fruData.size();
+ Response response(sizeof(pldm_msg_hdr) + respPayloadLength, 0);
+ auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
+
+ rc = encode_get_fru_record_by_option_resp(
+ request->hdr.instance_id, PLDM_SUCCESS, 0, PLDM_START_AND_END,
+ fruData.data(), fruData.size(), responsePtr, respPayloadLength);
+
+ if (rc != PLDM_SUCCESS)
+ {
+ return ccOnlyResponse(request, rc);
+ }
+
+ return response;
+}
+
} // namespace fru
} // namespace responder
diff --git a/libpldmresponder/fru.hpp b/libpldmresponder/fru.hpp
index 2597dc4..b19519c 100644
--- a/libpldmresponder/fru.hpp
+++ b/libpldmresponder/fru.hpp
@@ -106,6 +106,18 @@
*/
void getFRUTable(Response& response);
+ /** @brief Get FRU Record Table By Option
+ * @param[out] response - Populate response with the FRU table got by
+ * options
+ * @param[in] fruTableHandle - The fru table handle
+ * @param[in] recordSetIdentifer - The record set identifier
+ * @param[in] recordType - The record type
+ * @param[in] fieldType - The field type
+ */
+ int getFRURecordByOption(Response& response, uint16_t fruTableHandle,
+ uint16_t recordSetIdentifer, uint8_t recordType,
+ uint8_t fieldType);
+
/** @brief FRU table is built by processing the D-Bus inventory namespace
* based on the config files for FRU. The table is populated based
* on the isBuilt flag.
@@ -166,6 +178,11 @@
return this->getFRURecordTable(request,
payloadLength);
});
+ handlers.emplace(PLDM_GET_FRU_RECORD_BY_OPTION,
+ [this](const pldm_msg* request, size_t payloadLength) {
+ return this->getFRURecordByOption(request,
+ payloadLength);
+ });
}
/** @brief Handler for Get FRURecordTableMetadata
@@ -195,6 +212,16 @@
impl.buildFRUTable();
}
+ /** @brief Handler for GetFRURecordByOption
+ *
+ * @param[in] request - Request message payload
+ * @param[in] payloadLength - Request payload length
+ *
+ * @return PLDM response message
+ */
+ Response getFRURecordByOption(const pldm_msg* request,
+ size_t payloadLength);
+
private:
FruImpl impl;
};