Add HostPDRHandler class

HostPDRHandler has an API to fetch PDRs from the host.

The class HostPDRHandler has a function fetchPDR which basically calls
GetPDR on the host using libpldm's pldm_send_recv API.

The retrieved PDRs are stored in the BMCs primary PDR repo.

Change-Id: Ifd727316caf37d49f17e117b32ee105f6d941e0e
Signed-off-by: Pavithra Barithaya <pbaritha@in.ibm.com>
Signed-off-by: Deepak Kodihalli <dkodihal@in.ibm.com>
diff --git a/host_pdr_handler.cpp b/host_pdr_handler.cpp
new file mode 100644
index 0000000..1e78846
--- /dev/null
+++ b/host_pdr_handler.cpp
@@ -0,0 +1,81 @@
+#include "host_pdr_handler.hpp"
+
+#include "libpldm/requester/pldm.h"
+
+namespace pldm
+{
+
+void HostPDRHandler::fetchPDR(const std::vector<uint32_t>& recordHandles)
+{
+    std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) +
+                                    PLDM_GET_PDR_REQ_BYTES);
+    auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
+
+    for (auto recordHandle : recordHandles)
+    {
+        auto instanceId = requester.getInstanceId(mctp_eid);
+
+        auto rc =
+            encode_get_pdr_req(instanceId, recordHandle, 0, PLDM_GET_FIRSTPART,
+                               UINT16_MAX, 0, request, PLDM_GET_PDR_REQ_BYTES);
+        if (rc != PLDM_SUCCESS)
+        {
+            requester.markFree(mctp_eid, instanceId);
+            std::cerr << "Failed to encode_get_pdr_req, rc = " << rc << "\n";
+            return;
+        }
+
+        uint8_t* responseMsg = nullptr;
+        size_t responseMsgSize{};
+        auto requesterRc =
+            pldm_send_recv(mctp_eid, mctp_fd, requestMsg.data(),
+                           requestMsg.size(), &responseMsg, &responseMsgSize);
+        std::unique_ptr<uint8_t, decltype(std::free)*> responseMsgPtr{
+            responseMsg, std::free};
+        requester.markFree(mctp_eid, instanceId);
+        if (requesterRc != PLDM_REQUESTER_SUCCESS)
+        {
+            std::cerr << "Failed to send msg to fetch pdrs, rc = "
+                      << requesterRc << "\n";
+            return;
+        }
+
+        auto responsePtr =
+            reinterpret_cast<struct pldm_msg*>(responseMsgPtr.get());
+        uint8_t completionCode{};
+        uint32_t nextRecordHandle{};
+        uint32_t nextDataTransferHandle{};
+        uint8_t transferFlag{};
+        uint16_t respCount{};
+        uint8_t transferCRC{};
+        rc = decode_get_pdr_resp(
+            responsePtr, responseMsgSize - sizeof(pldm_msg_hdr),
+            &completionCode, &nextRecordHandle, &nextDataTransferHandle,
+            &transferFlag, &respCount, nullptr, 0, &transferCRC);
+        if (rc != PLDM_SUCCESS)
+        {
+            std::cerr << "Failed to decode_get_pdr_resp, rc = " << rc << "\n";
+        }
+        else
+        {
+            std::vector<uint8_t> pdr(respCount, 0);
+            rc = decode_get_pdr_resp(
+                responsePtr, responseMsgSize - sizeof(pldm_msg_hdr),
+                &completionCode, &nextRecordHandle, &nextDataTransferHandle,
+                &transferFlag, &respCount, pdr.data(), respCount, &transferCRC);
+            if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS)
+            {
+                std::cerr << "Failed to decode_get_pdr_resp: "
+                          << "rc=" << rc
+                          << ", cc=" << static_cast<int>(completionCode)
+                          << "\n";
+            }
+            else
+            {
+                pldm_pdr_add(repo, pdr.data(), respCount, 0);
+            }
+        }
+    }
+}
+
+} // namespace pldm