blob: c627b0b537984656ddc418351337eeb44690cf49 [file] [log] [blame]
Deepak Kodihalli87514cc2020-04-16 09:08:38 -05001#include "config.h"
2
Pavithra Barithaya51efaf82020-04-02 02:42:27 -05003#include "host_pdr_handler.hpp"
4
Deepak Kodihalli87514cc2020-04-16 09:08:38 -05005#include <fstream>
6#include <nlohmann/json.hpp>
7
Pavithra Barithaya51efaf82020-04-02 02:42:27 -05008#include "libpldm/requester/pldm.h"
9
10namespace pldm
11{
12
Deepak Kodihalli87514cc2020-04-16 09:08:38 -050013using Json = nlohmann::json;
14namespace fs = std::filesystem;
15constexpr auto fruJson = "host_frus.json";
16const Json emptyJson{};
17const std::vector<Json> emptyJsonList{};
18
19HostPDRHandler::HostPDRHandler(int mctp_fd, uint8_t mctp_eid,
20 sdeventplus::Event& event, pldm_pdr* repo,
21 pldm_entity_association_tree* entityTree,
22 Requester& requester) :
23 mctp_fd(mctp_fd),
24 mctp_eid(mctp_eid), event(event), repo(repo), entityTree(entityTree),
25 requester(requester)
26{
27 fs::path hostFruJson(fs::path(HOST_JSONS_DIR) / fruJson);
28 if (fs::exists(hostFruJson))
29 {
30 try
31 {
32 std::ifstream jsonFile(hostFruJson);
33 auto data = Json::parse(jsonFile, nullptr, false);
34 if (data.is_discarded())
35 {
36 std::cerr << "Parsing Host FRU json file failed" << std::endl;
37 }
38 else
39 {
40 auto entities = data.value("entities", emptyJsonList);
41 for (auto& entity : entities)
42 {
43 EntityType entityType = entity.value("entity_type", 0);
44 auto parent = entity.value("parent", emptyJson);
45 pldm_entity p{};
46 p.entity_type = parent.value("entity_type", 0);
47 p.entity_instance_num = parent.value("entity_instance", 0);
48 parents.emplace(entityType, std::move(p));
49 }
50 }
51 }
52 catch (const std::exception& e)
53 {
54 std::cerr << "Parsing Host FRU json file failed, exception = "
55 << e.what() << std::endl;
56 }
57 }
58}
59
Deepak Kodihalli8cb6f662020-04-10 02:55:43 -050060void HostPDRHandler::fetchPDR(std::vector<uint32_t>&& recordHandles)
Pavithra Barithaya51efaf82020-04-02 02:42:27 -050061{
Deepak Kodihalli8cb6f662020-04-10 02:55:43 -050062 pdrRecordHandles.clear();
63 pdrRecordHandles = std::move(recordHandles);
64
65 // Defer the actual fetch of PDRs from the host (by queuing the call on the
66 // main event loop). That way, we can respond to the platform event msg from
67 // the host firmware.
68 pdrFetchEvent = std::make_unique<sdeventplus::source::Defer>(
69 event, std::bind(std::mem_fn(&HostPDRHandler::_fetchPDR), this,
70 std::placeholders::_1));
71}
72
73void HostPDRHandler::_fetchPDR(sdeventplus::source::EventBase& /*source*/)
74{
75 pdrFetchEvent.reset();
76
Pavithra Barithaya51efaf82020-04-02 02:42:27 -050077 std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) +
78 PLDM_GET_PDR_REQ_BYTES);
79 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
80
Deepak Kodihalli8cb6f662020-04-10 02:55:43 -050081 for (auto recordHandle : pdrRecordHandles)
Pavithra Barithaya51efaf82020-04-02 02:42:27 -050082 {
83 auto instanceId = requester.getInstanceId(mctp_eid);
84
85 auto rc =
86 encode_get_pdr_req(instanceId, recordHandle, 0, PLDM_GET_FIRSTPART,
87 UINT16_MAX, 0, request, PLDM_GET_PDR_REQ_BYTES);
88 if (rc != PLDM_SUCCESS)
89 {
90 requester.markFree(mctp_eid, instanceId);
Deepak Kodihalli8cb6f662020-04-10 02:55:43 -050091 std::cerr << "Failed to encode_get_pdr_req, rc = " << rc
92 << std::endl;
Pavithra Barithaya51efaf82020-04-02 02:42:27 -050093 return;
94 }
95
96 uint8_t* responseMsg = nullptr;
97 size_t responseMsgSize{};
98 auto requesterRc =
99 pldm_send_recv(mctp_eid, mctp_fd, requestMsg.data(),
100 requestMsg.size(), &responseMsg, &responseMsgSize);
101 std::unique_ptr<uint8_t, decltype(std::free)*> responseMsgPtr{
102 responseMsg, std::free};
103 requester.markFree(mctp_eid, instanceId);
104 if (requesterRc != PLDM_REQUESTER_SUCCESS)
105 {
106 std::cerr << "Failed to send msg to fetch pdrs, rc = "
Deepak Kodihalli8cb6f662020-04-10 02:55:43 -0500107 << requesterRc << std::endl;
Pavithra Barithaya51efaf82020-04-02 02:42:27 -0500108 return;
109 }
110
111 auto responsePtr =
112 reinterpret_cast<struct pldm_msg*>(responseMsgPtr.get());
113 uint8_t completionCode{};
114 uint32_t nextRecordHandle{};
115 uint32_t nextDataTransferHandle{};
116 uint8_t transferFlag{};
117 uint16_t respCount{};
118 uint8_t transferCRC{};
119 rc = decode_get_pdr_resp(
120 responsePtr, responseMsgSize - sizeof(pldm_msg_hdr),
121 &completionCode, &nextRecordHandle, &nextDataTransferHandle,
122 &transferFlag, &respCount, nullptr, 0, &transferCRC);
123 if (rc != PLDM_SUCCESS)
124 {
Deepak Kodihalli8cb6f662020-04-10 02:55:43 -0500125 std::cerr << "Failed to decode_get_pdr_resp, rc = " << rc
126 << std::endl;
Pavithra Barithaya51efaf82020-04-02 02:42:27 -0500127 }
128 else
129 {
130 std::vector<uint8_t> pdr(respCount, 0);
131 rc = decode_get_pdr_resp(
132 responsePtr, responseMsgSize - sizeof(pldm_msg_hdr),
133 &completionCode, &nextRecordHandle, &nextDataTransferHandle,
134 &transferFlag, &respCount, pdr.data(), respCount, &transferCRC);
135 if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS)
136 {
137 std::cerr << "Failed to decode_get_pdr_resp: "
138 << "rc=" << rc
Deepak Kodihalli8cb6f662020-04-10 02:55:43 -0500139 << ", cc=" << static_cast<unsigned>(completionCode)
140 << std::endl;
Pavithra Barithaya51efaf82020-04-02 02:42:27 -0500141 }
142 else
143 {
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500144 auto pdrHdr = reinterpret_cast<pldm_pdr_hdr*>(pdr.data());
145 if (pdrHdr->type == PLDM_PDR_ENTITY_ASSOCIATION)
146 {
147 mergeEntityAssociations(pdr);
148 }
149 else
150 {
151 pldm_pdr_add(repo, pdr.data(), respCount, 0, true);
152 }
Pavithra Barithaya51efaf82020-04-02 02:42:27 -0500153 }
154 }
155 }
156}
157
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500158bool HostPDRHandler::getParent(EntityType type, pldm_entity& parent)
159{
160 auto found = parents.find(type);
161 if (found != parents.end())
162 {
163 parent.entity_type = found->second.entity_type;
164 parent.entity_instance_num = found->second.entity_instance_num;
165 return true;
166 }
167
168 return false;
169}
170
171void HostPDRHandler::mergeEntityAssociations(const std::vector<uint8_t>& pdr)
172{
173 size_t numEntities{};
174 pldm_entity* entities = nullptr;
175 bool merged = false;
176 auto entityPdr = reinterpret_cast<pldm_pdr_entity_association*>(
177 const_cast<uint8_t*>(pdr.data()) + sizeof(pldm_pdr_hdr));
178
179 pldm_entity_association_pdr_extract(pdr.data(), pdr.size(), &numEntities,
180 &entities);
181 for (size_t i = 0; i < numEntities; ++i)
182 {
183 pldm_entity parent{};
184 if (getParent(entities[i].entity_type, parent))
185 {
186 auto node = pldm_entity_association_tree_find(entityTree, &parent);
187 if (node)
188 {
189 pldm_entity_association_tree_add(entityTree, &entities[i], node,
190 entityPdr->association_type);
191 merged = true;
192 }
193 }
194 }
195 free(entities);
196
197 if (merged)
198 {
199 pldm_entity_association_pdr_add(entityTree, repo, true);
200 }
201}
202
Pavithra Barithaya51efaf82020-04-02 02:42:27 -0500203} // namespace pldm