blob: 32993eeffd9956cdd12c105b67672f1b9f8a9294 [file] [log] [blame]
Pavithra Barithaya51efaf82020-04-02 02:42:27 -05001#include "host_pdr_handler.hpp"
2
George Liu682ee182020-12-25 15:24:33 +08003#include "libpldm/fru.h"
4#ifdef OEM_IBM
5#include "libpldm/fru_oem_ibm.h"
6#endif
7
8#include "custom_dbus.hpp"
9
Pavithra Barithayae8beb892020-04-14 23:24:25 -050010#include <assert.h>
George Liuc453e162022-12-21 17:16:23 +080011#include <libpldm/pldm.h>
Pavithra Barithayae8beb892020-04-14 23:24:25 -050012
Deepak Kodihalli87514cc2020-04-16 09:08:38 -050013#include <nlohmann/json.hpp>
Riya Dixit49cfb132023-03-02 04:26:53 -060014#include <phosphor-logging/lg2.hpp>
sampmisr6decfc12021-03-02 11:07:36 +053015#include <sdeventplus/clock.hpp>
16#include <sdeventplus/exception.hpp>
17#include <sdeventplus/source/io.hpp>
18#include <sdeventplus/source/time.hpp>
Deepak Kodihalli87514cc2020-04-16 09:08:38 -050019
George Liu6492f522020-06-16 10:34:05 +080020#include <fstream>
Pavithra Barithaya51efaf82020-04-02 02:42:27 -050021
Riya Dixit49cfb132023-03-02 04:26:53 -060022PHOSPHOR_LOG2_USING;
23
Pavithra Barithaya51efaf82020-04-02 02:42:27 -050024namespace pldm
25{
Brad Bishop5079ac42021-08-19 18:35:06 -040026using namespace pldm::responder::events;
Deepak Kodihalli6b1d1ca2020-04-27 07:24:51 -050027using namespace pldm::utils;
28using namespace sdbusplus::bus::match::rules;
Deepak Kodihalli87514cc2020-04-16 09:08:38 -050029using Json = nlohmann::json;
30namespace fs = std::filesystem;
George Liu682ee182020-12-25 15:24:33 +080031using namespace pldm::dbus;
Deepak Kodihalli87514cc2020-04-16 09:08:38 -050032constexpr auto fruJson = "host_frus.json";
33const Json emptyJson{};
34const std::vector<Json> emptyJsonList{};
35
Manojkiran Eda3ca40452021-10-04 22:51:37 +053036template <typename T>
37uint16_t extractTerminusHandle(std::vector<uint8_t>& pdr)
38{
39 T* var = nullptr;
40 if (std::is_same<T, pldm_pdr_fru_record_set>::value)
41 {
42 var = (T*)(pdr.data() + sizeof(pldm_pdr_hdr));
43 }
44 else
45 {
46 var = (T*)(pdr.data());
47 }
48 if (var != nullptr)
49 {
50 return var->terminus_handle;
51 }
52 return TERMINUS_HANDLE;
53}
54
Tom Joseph74f27c72021-05-16 07:58:53 -070055HostPDRHandler::HostPDRHandler(
56 int mctp_fd, uint8_t mctp_eid, sdeventplus::Event& event, pldm_pdr* repo,
57 const std::string& eventsJsonsDir, pldm_entity_association_tree* entityTree,
Andrew Jefferya330b2f2023-05-04 14:55:37 +093058 pldm_entity_association_tree* bmcEntityTree,
59 pldm::InstanceIdDb& instanceIdDb,
Tom Josephe5268cd2021-09-07 13:04:03 +053060 pldm::requester::Handler<pldm::requester::Request>* handler) :
Deepak Kodihalli87514cc2020-04-16 09:08:38 -050061 mctp_fd(mctp_fd),
Pavithra Barithaya3aec9972020-12-14 01:55:44 -060062 mctp_eid(mctp_eid), event(event), repo(repo),
63 stateSensorHandler(eventsJsonsDir), entityTree(entityTree),
Andrew Jefferya330b2f2023-05-04 14:55:37 +093064 bmcEntityTree(bmcEntityTree), instanceIdDb(instanceIdDb), handler(handler)
Deepak Kodihalli87514cc2020-04-16 09:08:38 -050065{
George Liuacf2c8c2021-05-10 14:08:52 +080066 mergedHostParents = false;
Deepak Kodihalli87514cc2020-04-16 09:08:38 -050067 fs::path hostFruJson(fs::path(HOST_JSONS_DIR) / fruJson);
68 if (fs::exists(hostFruJson))
69 {
Pavithra Barithayae8beb892020-04-14 23:24:25 -050070 // Note parent entities for entities sent down by the host firmware.
71 // This will enable a merge of entity associations.
Deepak Kodihalli87514cc2020-04-16 09:08:38 -050072 try
73 {
74 std::ifstream jsonFile(hostFruJson);
75 auto data = Json::parse(jsonFile, nullptr, false);
76 if (data.is_discarded())
77 {
Riya Dixit49cfb132023-03-02 04:26:53 -060078 error("Parsing Host FRU json file failed");
Deepak Kodihalli87514cc2020-04-16 09:08:38 -050079 }
80 else
81 {
82 auto entities = data.value("entities", emptyJsonList);
83 for (auto& entity : entities)
84 {
85 EntityType entityType = entity.value("entity_type", 0);
86 auto parent = entity.value("parent", emptyJson);
87 pldm_entity p{};
88 p.entity_type = parent.value("entity_type", 0);
89 p.entity_instance_num = parent.value("entity_instance", 0);
90 parents.emplace(entityType, std::move(p));
91 }
92 }
93 }
94 catch (const std::exception& e)
95 {
Riya Dixit49cfb132023-03-02 04:26:53 -060096 error("Parsing Host FRU json file failed, exception = {ERR_EXCEP}",
97 "ERR_EXCEP", e.what());
Deepak Kodihalli87514cc2020-04-16 09:08:38 -050098 }
99 }
Deepak Kodihalli6b1d1ca2020-04-27 07:24:51 -0500100
Patrick Williams84b790c2022-07-22 19:26:56 -0500101 hostOffMatch = std::make_unique<sdbusplus::bus::match_t>(
Deepak Kodihalli6b1d1ca2020-04-27 07:24:51 -0500102 pldm::utils::DBusHandler::getBus(),
103 propertiesChanged("/xyz/openbmc_project/state/host0",
104 "xyz.openbmc_project.State.Host"),
Patrick Williams84b790c2022-07-22 19:26:56 -0500105 [this, repo, entityTree, bmcEntityTree](sdbusplus::message_t& msg) {
Patrick Williams6da4f912023-05-10 07:50:53 -0500106 DbusChangedProps props{};
107 std::string intf;
108 msg.read(intf, props);
109 const auto itr = props.find("CurrentHostState");
110 if (itr != props.end())
111 {
112 PropertyValue value = itr->second;
113 auto propVal = std::get<std::string>(value);
114 if (propVal == "xyz.openbmc_project.State.Host.HostState.Off")
Deepak Kodihalli6b1d1ca2020-04-27 07:24:51 -0500115 {
Patrick Williams6da4f912023-05-10 07:50:53 -0500116 // Delete all the remote terminus information
117 std::erase_if(tlPDRInfo, [](const auto& item) {
118 auto const& [key, value] = item;
119 return key != TERMINUS_HANDLE;
120 });
121 pldm_pdr_remove_remote_pdrs(repo);
122 pldm_entity_association_tree_destroy_root(entityTree);
123 pldm_entity_association_tree_copy_root(bmcEntityTree,
124 entityTree);
125 this->sensorMap.clear();
126 this->responseReceived = false;
George Liuacf2c8c2021-05-10 14:08:52 +0800127 this->mergedHostParents = false;
Deepak Kodihalli6b1d1ca2020-04-27 07:24:51 -0500128 }
Patrick Williams6da4f912023-05-10 07:50:53 -0500129 }
Deepak Kodihalli6b1d1ca2020-04-27 07:24:51 -0500130 });
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500131}
132
Deepak Kodihalli7246e0c2020-07-08 06:40:18 -0500133void HostPDRHandler::fetchPDR(PDRRecordHandles&& recordHandles)
Pavithra Barithaya51efaf82020-04-02 02:42:27 -0500134{
Deepak Kodihalli8cb6f662020-04-10 02:55:43 -0500135 pdrRecordHandles.clear();
Pavithra Barithayaae5c97e2022-08-29 02:57:59 -0500136 modifiedPDRRecordHandles.clear();
137
138 if (isHostPdrModified)
139 {
140 modifiedPDRRecordHandles = std::move(recordHandles);
141 }
142 else
143 {
144 pdrRecordHandles = std::move(recordHandles);
145 }
Deepak Kodihalli8cb6f662020-04-10 02:55:43 -0500146
147 // Defer the actual fetch of PDRs from the host (by queuing the call on the
148 // main event loop). That way, we can respond to the platform event msg from
149 // the host firmware.
150 pdrFetchEvent = std::make_unique<sdeventplus::source::Defer>(
151 event, std::bind(std::mem_fn(&HostPDRHandler::_fetchPDR), this,
152 std::placeholders::_1));
153}
154
155void HostPDRHandler::_fetchPDR(sdeventplus::source::EventBase& /*source*/)
156{
Sampa Misrac0c79482021-06-02 08:01:54 -0500157 getHostPDR();
158}
159
160void HostPDRHandler::getHostPDR(uint32_t nextRecordHandle)
161{
Deepak Kodihalli8cb6f662020-04-10 02:55:43 -0500162 pdrFetchEvent.reset();
163
Pavithra Barithaya51efaf82020-04-02 02:42:27 -0500164 std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) +
165 PLDM_GET_PDR_REQ_BYTES);
166 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
Deepak Kodihalli7246e0c2020-07-08 06:40:18 -0500167 uint32_t recordHandle{};
Pavithra Barithayaae5c97e2022-08-29 02:57:59 -0500168 if (!nextRecordHandle && (!modifiedPDRRecordHandles.empty()) &&
169 isHostPdrModified)
Deepak Kodihalli7246e0c2020-07-08 06:40:18 -0500170 {
Pavithra Barithayaae5c97e2022-08-29 02:57:59 -0500171 recordHandle = modifiedPDRRecordHandles.front();
172 modifiedPDRRecordHandles.pop_front();
173 }
174 else if (!nextRecordHandle && (!pdrRecordHandles.empty()))
175 {
176 recordHandle = pdrRecordHandles.front();
177 pdrRecordHandles.pop_front();
Sampa Misrac0c79482021-06-02 08:01:54 -0500178 }
179 else
180 {
181 recordHandle = nextRecordHandle;
182 }
Andrew Jefferya330b2f2023-05-04 14:55:37 +0930183 auto instanceId = instanceIdDb.next(mctp_eid);
Sampa Misrac0c79482021-06-02 08:01:54 -0500184
Patrick Williams6da4f912023-05-10 07:50:53 -0500185 auto rc = encode_get_pdr_req(instanceId, recordHandle, 0,
186 PLDM_GET_FIRSTPART, UINT16_MAX, 0, request,
187 PLDM_GET_PDR_REQ_BYTES);
Sampa Misrac0c79482021-06-02 08:01:54 -0500188 if (rc != PLDM_SUCCESS)
189 {
Andrew Jefferya330b2f2023-05-04 14:55:37 +0930190 instanceIdDb.free(mctp_eid, instanceId);
Riya Dixit49cfb132023-03-02 04:26:53 -0600191 error("Failed to encode_get_pdr_req, rc = {RC}", "RC", rc);
Sampa Misrac0c79482021-06-02 08:01:54 -0500192 return;
193 }
Deepak Kodihalli7246e0c2020-07-08 06:40:18 -0500194
Sampa Misrac0c79482021-06-02 08:01:54 -0500195 rc = handler->registerRequest(
196 mctp_eid, instanceId, PLDM_PLATFORM, PLDM_GET_PDR,
197 std::move(requestMsg),
198 std::move(std::bind_front(&HostPDRHandler::processHostPDRs, this)));
199 if (rc)
Pavithra Barithaya51efaf82020-04-02 02:42:27 -0500200 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600201 error("Failed to send the GetPDR request to Host");
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500202 }
Pavithra Barithaya51efaf82020-04-02 02:42:27 -0500203}
204
Pavithra Barithaya3aec9972020-12-14 01:55:44 -0600205int HostPDRHandler::handleStateSensorEvent(const StateSensorEntry& entry,
206 pdr::EventState state)
207{
208 auto rc = stateSensorHandler.eventAction(entry, state);
209 if (rc != PLDM_SUCCESS)
210 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600211 error("Failed to fetch and update D-bus property, rc = {RC}", "RC", rc);
Pavithra Barithaya3aec9972020-12-14 01:55:44 -0600212 return rc;
213 }
214 return PLDM_SUCCESS;
215}
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500216
217void HostPDRHandler::mergeEntityAssociations(const std::vector<uint8_t>& pdr)
218{
219 size_t numEntities{};
220 pldm_entity* entities = nullptr;
221 bool merged = false;
222 auto entityPdr = reinterpret_cast<pldm_pdr_entity_association*>(
223 const_cast<uint8_t*>(pdr.data()) + sizeof(pldm_pdr_hdr));
224
225 pldm_entity_association_pdr_extract(pdr.data(), pdr.size(), &numEntities,
226 &entities);
George Liuacf2c8c2021-05-10 14:08:52 +0800227 if (numEntities > 0)
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500228 {
George Liuacf2c8c2021-05-10 14:08:52 +0800229 pldm_entity_node* pNode = nullptr;
230 if (!mergedHostParents)
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500231 {
George Liuacf2c8c2021-05-10 14:08:52 +0800232 pNode = pldm_entity_association_tree_find_with_locality(
233 entityTree, &entities[0], false);
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500234 }
George Liuacf2c8c2021-05-10 14:08:52 +0800235 else
236 {
237 pNode = pldm_entity_association_tree_find_with_locality(
238 entityTree, &entities[0], true);
239 }
240 if (!pNode)
241 {
242 return;
243 }
244
George Liudf9a6d32020-12-22 16:27:16 +0800245 Entities entityAssoc;
246 entityAssoc.push_back(pNode);
George Liuacf2c8c2021-05-10 14:08:52 +0800247 for (size_t i = 1; i < numEntities; ++i)
248 {
George Liudf9a6d32020-12-22 16:27:16 +0800249 auto node = pldm_entity_association_tree_add_entity(
George Liuacf2c8c2021-05-10 14:08:52 +0800250 entityTree, &entities[i], entities[i].entity_instance_num,
251 pNode, entityPdr->association_type, true, true, 0xFFFF);
252 merged = true;
George Liudf9a6d32020-12-22 16:27:16 +0800253 entityAssoc.push_back(node);
George Liuacf2c8c2021-05-10 14:08:52 +0800254 }
255
256 mergedHostParents = true;
George Liudf9a6d32020-12-22 16:27:16 +0800257 if (merged)
258 {
259 entityAssociations.push_back(entityAssoc);
260 }
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500261 }
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500262
263 if (merged)
264 {
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500265 // Update our PDR repo with the merged entity association PDRs
Sampa Misra719ed392021-06-04 05:15:13 -0500266 pldm_entity_node* node = nullptr;
267 pldm_find_entity_ref_in_tree(entityTree, entities[0], &node);
268 if (node == nullptr)
269 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600270 error("could not find referrence of the entity in the tree");
Sampa Misra719ed392021-06-04 05:15:13 -0500271 }
272 else
273 {
Andrew Jeffery1fd3c512023-07-03 13:02:03 +0930274 int rc = pldm_entity_association_pdr_add_from_node_check(
Manojkiran Eda3ca40452021-10-04 22:51:37 +0530275 node, repo, &entities, numEntities, true, TERMINUS_HANDLE);
Andrew Jeffery1fd3c512023-07-03 13:02:03 +0930276 if (rc)
277 {
278 error(
279 "Failed to add entity association PDR from node: {LIBPLDM_ERROR}",
280 "LIBPLDM_ERROR", rc);
281 }
Sampa Misra719ed392021-06-04 05:15:13 -0500282 }
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500283 }
Sampa Misra719ed392021-06-04 05:15:13 -0500284 free(entities);
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500285}
286
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500287void HostPDRHandler::sendPDRRepositoryChgEvent(std::vector<uint8_t>&& pdrTypes,
288 uint8_t eventDataFormat)
289{
290 assert(eventDataFormat == FORMAT_IS_PDR_HANDLES);
291
292 // Extract from the PDR repo record handles of PDRs we want the host
293 // to pull up.
294 std::vector<uint8_t> eventDataOps{PLDM_RECORDS_ADDED};
295 std::vector<uint8_t> numsOfChangeEntries(1);
296 std::vector<std::vector<ChangeEntry>> changeEntries(
297 numsOfChangeEntries.size());
298 for (auto pdrType : pdrTypes)
299 {
300 const pldm_pdr_record* record{};
301 do
302 {
303 record = pldm_pdr_find_record_by_type(repo, pdrType, record,
304 nullptr, nullptr);
305 if (record && pldm_pdr_record_is_remote(record))
306 {
307 changeEntries[0].push_back(
308 pldm_pdr_get_record_handle(repo, record));
309 }
310 } while (record);
311 }
312 if (changeEntries.empty())
313 {
314 return;
315 }
316 numsOfChangeEntries[0] = changeEntries[0].size();
317
318 // Encode PLDM platform event msg to indicate a PDR repo change.
319 size_t maxSize = PLDM_PDR_REPOSITORY_CHG_EVENT_MIN_LENGTH +
320 PLDM_PDR_REPOSITORY_CHANGE_RECORD_MIN_LENGTH +
321 changeEntries[0].size() * sizeof(uint32_t);
322 std::vector<uint8_t> eventDataVec{};
323 eventDataVec.resize(maxSize);
324 auto eventData =
325 reinterpret_cast<struct pldm_pdr_repository_chg_event_data*>(
326 eventDataVec.data());
327 size_t actualSize{};
328 auto firstEntry = changeEntries[0].data();
329 auto rc = encode_pldm_pdr_repository_chg_event_data(
330 eventDataFormat, 1, eventDataOps.data(), numsOfChangeEntries.data(),
331 &firstEntry, eventData, &actualSize, maxSize);
332 if (rc != PLDM_SUCCESS)
333 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600334 error("Failed to encode_pldm_pdr_repository_chg_event_data, rc = {RC}",
335 "RC", rc);
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500336 return;
337 }
Andrew Jefferya330b2f2023-05-04 14:55:37 +0930338 auto instanceId = instanceIdDb.next(mctp_eid);
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500339 std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) +
340 PLDM_PLATFORM_EVENT_MESSAGE_MIN_REQ_BYTES +
341 actualSize);
342 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
343 rc = encode_platform_event_message_req(
ArchanaKakani6c39c7a2022-12-05 04:36:35 -0600344 instanceId, 1, TERMINUS_ID, PLDM_PDR_REPOSITORY_CHG_EVENT,
345 eventDataVec.data(), actualSize, request,
Christian Geddes3bdb3c22020-05-01 14:55:39 -0500346 actualSize + PLDM_PLATFORM_EVENT_MESSAGE_MIN_REQ_BYTES);
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500347 if (rc != PLDM_SUCCESS)
348 {
Andrew Jefferya330b2f2023-05-04 14:55:37 +0930349 instanceIdDb.free(mctp_eid, instanceId);
Riya Dixit49cfb132023-03-02 04:26:53 -0600350 error("Failed to encode_platform_event_message_req, rc = {RC}", "RC",
351 rc);
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500352 return;
353 }
354
Patrick Williams6da4f912023-05-10 07:50:53 -0500355 auto platformEventMessageResponseHandler =
356 [](mctp_eid_t /*eid*/, const pldm_msg* response, size_t respMsgLen) {
Tom Joseph74f27c72021-05-16 07:58:53 -0700357 if (response == nullptr || !respMsgLen)
358 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600359 error(
360 "Failed to receive response for the PDR repository changed event");
Tom Joseph74f27c72021-05-16 07:58:53 -0700361 return;
362 }
363
364 uint8_t completionCode{};
365 uint8_t status{};
366 auto responsePtr = reinterpret_cast<const struct pldm_msg*>(response);
Pavithra Barithaya54b5a562021-09-27 06:07:10 -0500367 auto rc = decode_platform_event_message_resp(responsePtr, respMsgLen,
368 &completionCode, &status);
Sampa Misrac0c79482021-06-02 08:01:54 -0500369 if (rc || completionCode)
Tom Joseph74f27c72021-05-16 07:58:53 -0700370 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600371 error(
372 "Failed to decode_platform_event_message_resp: {RC}, cc = {CC}",
373 "RC", rc, "CC", static_cast<unsigned>(completionCode));
Tom Joseph74f27c72021-05-16 07:58:53 -0700374 }
375 };
376
Sampa Misrac0c79482021-06-02 08:01:54 -0500377 rc = handler->registerRequest(
Sampa Misra626c5652021-08-11 10:28:48 -0500378 mctp_eid, instanceId, PLDM_PLATFORM, PLDM_PLATFORM_EVENT_MESSAGE,
Tom Joseph74f27c72021-05-16 07:58:53 -0700379 std::move(requestMsg), std::move(platformEventMessageResponseHandler));
Sampa Misrac0c79482021-06-02 08:01:54 -0500380 if (rc)
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500381 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600382 error("Failed to send the PDR repository changed event request");
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500383 }
384}
385
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530386void HostPDRHandler::parseStateSensorPDRs(const PDRList& stateSensorPDRs)
Sampa Misra868c8792020-05-26 03:12:13 -0500387{
388 for (const auto& pdr : stateSensorPDRs)
389 {
390 SensorEntry sensorEntry{};
391 const auto& [terminusHandle, sensorID, sensorInfo] =
392 responder::pdr_utils::parseStateSensorPDR(pdr);
393 sensorEntry.sensorID = sensorID;
394 try
395 {
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530396 sensorEntry.terminusID = std::get<0>(tlPDRInfo.at(terminusHandle));
Sampa Misra868c8792020-05-26 03:12:13 -0500397 }
398 // If there is no mapping for terminusHandle assign the reserved TID
399 // value of 0xFF to indicate that.
400 catch (const std::out_of_range& e)
401 {
402 sensorEntry.terminusID = PLDM_TID_RESERVED;
403 }
404 sensorMap.emplace(sensorEntry, std::move(sensorInfo));
405 }
406}
407
Sampa Misrac0c79482021-06-02 08:01:54 -0500408void HostPDRHandler::processHostPDRs(mctp_eid_t /*eid*/,
409 const pldm_msg* response,
410 size_t respMsgLen)
411{
412 static bool merged = false;
413 static PDRList stateSensorPDRs{};
George Liu682ee182020-12-25 15:24:33 +0800414 static PDRList fruRecordSetPDRs{};
Sampa Misrac0c79482021-06-02 08:01:54 -0500415 uint32_t nextRecordHandle{};
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600416 uint8_t tlEid = 0;
417 bool tlValid = true;
418 uint32_t rh = 0;
419 uint16_t terminusHandle = 0;
Manojkiran Eda3ca40452021-10-04 22:51:37 +0530420 uint16_t pdrTerminusHandle = 0;
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600421 uint8_t tid = 0;
422
Sampa Misrac0c79482021-06-02 08:01:54 -0500423 uint8_t completionCode{};
424 uint32_t nextDataTransferHandle{};
425 uint8_t transferFlag{};
426 uint16_t respCount{};
427 uint8_t transferCRC{};
428 if (response == nullptr || !respMsgLen)
429 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600430 error("Failed to receive response for the GetPDR command");
Sampa Misrac0c79482021-06-02 08:01:54 -0500431 return;
432 }
433
434 auto rc = decode_get_pdr_resp(
435 response, respMsgLen /*- sizeof(pldm_msg_hdr)*/, &completionCode,
436 &nextRecordHandle, &nextDataTransferHandle, &transferFlag, &respCount,
437 nullptr, 0, &transferCRC);
438 std::vector<uint8_t> responsePDRMsg;
439 responsePDRMsg.resize(respMsgLen + sizeof(pldm_msg_hdr));
440 memcpy(responsePDRMsg.data(), response, respMsgLen + sizeof(pldm_msg_hdr));
Sampa Misrac0c79482021-06-02 08:01:54 -0500441 if (rc != PLDM_SUCCESS)
442 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600443 error("Failed to decode_get_pdr_resp, rc = {RC}", "RC", rc);
Sampa Misrac0c79482021-06-02 08:01:54 -0500444 return;
445 }
446 else
447 {
448 std::vector<uint8_t> pdr(respCount, 0);
449 rc = decode_get_pdr_resp(response, respMsgLen, &completionCode,
450 &nextRecordHandle, &nextDataTransferHandle,
451 &transferFlag, &respCount, pdr.data(),
452 respCount, &transferCRC);
453 if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS)
454 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600455 error("Failed to decode_get_pdr_resp: rc = {RC}, cc = {CC}", "RC",
456 rc, "CC", static_cast<unsigned>(completionCode));
Sampa Misrac0c79482021-06-02 08:01:54 -0500457 return;
458 }
459 else
460 {
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600461 // when nextRecordHandle is 0, we need the recordHandle of the last
462 // PDR and not 0-1.
463 if (!nextRecordHandle)
464 {
465 rh = nextRecordHandle;
466 }
467 else
468 {
469 rh = nextRecordHandle - 1;
470 }
471
Sampa Misrac0c79482021-06-02 08:01:54 -0500472 auto pdrHdr = reinterpret_cast<pldm_pdr_hdr*>(pdr.data());
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600473 if (!rh)
474 {
475 rh = pdrHdr->record_handle;
476 }
477
Sampa Misrac0c79482021-06-02 08:01:54 -0500478 if (pdrHdr->type == PLDM_PDR_ENTITY_ASSOCIATION)
479 {
480 this->mergeEntityAssociations(pdr);
481 merged = true;
482 }
483 else
484 {
485 if (pdrHdr->type == PLDM_TERMINUS_LOCATOR_PDR)
486 {
Manojkiran Eda3ca40452021-10-04 22:51:37 +0530487 pdrTerminusHandle =
488 extractTerminusHandle<pldm_terminus_locator_pdr>(pdr);
Sampa Misrac0c79482021-06-02 08:01:54 -0500489 auto tlpdr =
490 reinterpret_cast<const pldm_terminus_locator_pdr*>(
491 pdr.data());
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600492
493 terminusHandle = tlpdr->terminus_handle;
494 tid = tlpdr->tid;
495 auto terminus_locator_type = tlpdr->terminus_locator_type;
496 if (terminus_locator_type ==
497 PLDM_TERMINUS_LOCATOR_TYPE_MCTP_EID)
498 {
499 auto locatorValue = reinterpret_cast<
500 const pldm_terminus_locator_type_mctp_eid*>(
501 tlpdr->terminus_locator_value);
502 tlEid = static_cast<uint8_t>(locatorValue->eid);
503 }
504 if (tlpdr->validity == 0)
505 {
506 tlValid = false;
507 }
Pavithra Barithaya52aad392022-08-02 04:18:52 -0500508 for (const auto& terminusMap : tlPDRInfo)
509 {
510 if ((terminusHandle == (terminusMap.first)) &&
511 (get<1>(terminusMap.second) == tlEid) &&
512 (get<2>(terminusMap.second) == tlpdr->validity))
513 {
514 // TL PDR already present with same validity don't
515 // add the PDR to the repo just return
516 return;
517 }
518 }
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530519 tlPDRInfo.insert_or_assign(
520 tlpdr->terminus_handle,
521 std::make_tuple(tlpdr->tid, tlEid, tlpdr->validity));
Sampa Misrac0c79482021-06-02 08:01:54 -0500522 }
523 else if (pdrHdr->type == PLDM_STATE_SENSOR_PDR)
524 {
Manojkiran Eda3ca40452021-10-04 22:51:37 +0530525 pdrTerminusHandle =
526 extractTerminusHandle<pldm_state_sensor_pdr>(pdr);
Sampa Misrac0c79482021-06-02 08:01:54 -0500527 stateSensorPDRs.emplace_back(pdr);
528 }
Manojkiran Eda3ca40452021-10-04 22:51:37 +0530529 else if (pdrHdr->type == PLDM_PDR_FRU_RECORD_SET)
530 {
531 pdrTerminusHandle =
532 extractTerminusHandle<pldm_pdr_fru_record_set>(pdr);
George Liu682ee182020-12-25 15:24:33 +0800533 fruRecordSetPDRs.emplace_back(pdr);
Manojkiran Eda3ca40452021-10-04 22:51:37 +0530534 }
535 else if (pdrHdr->type == PLDM_STATE_EFFECTER_PDR)
536 {
537 pdrTerminusHandle =
538 extractTerminusHandle<pldm_state_effecter_pdr>(pdr);
539 }
540 else if (pdrHdr->type == PLDM_NUMERIC_EFFECTER_PDR)
541 {
542 pdrTerminusHandle =
543 extractTerminusHandle<pldm_numeric_effecter_value_pdr>(
544 pdr);
545 }
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600546 // if the TLPDR is invalid update the repo accordingly
547 if (!tlValid)
548 {
549 pldm_pdr_update_TL_pdr(repo, terminusHandle, tid, tlEid,
550 tlValid);
551 }
552 else
553 {
Andrew Jeffery64f37fe2023-07-03 15:41:13 +0930554 rc = pldm_pdr_add_check(repo, pdr.data(), respCount, true,
555 pdrTerminusHandle, &rh);
556 if (rc)
557 {
558 // pldm_pdr_add() assert()ed on failure to add a PDR.
559 throw std::runtime_error("Failed to add PDR");
560 }
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600561 }
Sampa Misrac0c79482021-06-02 08:01:54 -0500562 }
563 }
564 }
565 if (!nextRecordHandle)
566 {
George Liudf9a6d32020-12-22 16:27:16 +0800567 updateEntityAssociation(entityAssociations, entityTree, objPathMap);
568
Sampa Misrac0c79482021-06-02 08:01:54 -0500569 /*received last record*/
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530570 this->parseStateSensorPDRs(stateSensorPDRs);
George Liu682ee182020-12-25 15:24:33 +0800571 this->createDbusObjects(fruRecordSetPDRs);
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600572 if (isHostUp())
573 {
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530574 this->setHostSensorState(stateSensorPDRs);
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600575 }
Sampa Misrac0c79482021-06-02 08:01:54 -0500576 stateSensorPDRs.clear();
George Liu682ee182020-12-25 15:24:33 +0800577 fruRecordSetPDRs.clear();
George Liudf9a6d32020-12-22 16:27:16 +0800578 entityAssociations.clear();
579
Sampa Misrac0c79482021-06-02 08:01:54 -0500580 if (merged)
581 {
582 merged = false;
583 deferredPDRRepoChgEvent =
584 std::make_unique<sdeventplus::source::Defer>(
585 event,
586 std::bind(
587 std::mem_fn((&HostPDRHandler::_processPDRRepoChgEvent)),
588 this, std::placeholders::_1));
589 }
590 }
591 else
592 {
Pavithra Barithayaae5c97e2022-08-29 02:57:59 -0500593 if (modifiedPDRRecordHandles.empty() && isHostPdrModified)
594 {
595 isHostPdrModified = false;
596 }
597 else
598 {
599 deferredFetchPDREvent =
600 std::make_unique<sdeventplus::source::Defer>(
601 event,
602 std::bind(
603 std::mem_fn((&HostPDRHandler::_processFetchPDREvent)),
604 this, nextRecordHandle, std::placeholders::_1));
605 }
Sampa Misrac0c79482021-06-02 08:01:54 -0500606 }
607}
608
609void HostPDRHandler::_processPDRRepoChgEvent(
610 sdeventplus::source::EventBase& /*source */)
611{
612 deferredPDRRepoChgEvent.reset();
613 this->sendPDRRepositoryChgEvent(
614 std::move(std::vector<uint8_t>(1, PLDM_PDR_ENTITY_ASSOCIATION)),
615 FORMAT_IS_PDR_HANDLES);
616}
617
618void HostPDRHandler::_processFetchPDREvent(
619 uint32_t nextRecordHandle, sdeventplus::source::EventBase& /*source */)
620{
621 deferredFetchPDREvent.reset();
622 if (!this->pdrRecordHandles.empty())
623 {
624 nextRecordHandle = this->pdrRecordHandles.front();
625 this->pdrRecordHandles.pop_front();
626 }
Pavithra Barithayaae5c97e2022-08-29 02:57:59 -0500627 if (isHostPdrModified && (!this->modifiedPDRRecordHandles.empty()))
628 {
629 nextRecordHandle = this->modifiedPDRRecordHandles.front();
630 this->modifiedPDRRecordHandles.pop_front();
631 }
Sampa Misrac0c79482021-06-02 08:01:54 -0500632 this->getHostPDR(nextRecordHandle);
633}
634
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500635void HostPDRHandler::setHostFirmwareCondition()
sampmisr6decfc12021-03-02 11:07:36 +0530636{
sampmisr6decfc12021-03-02 11:07:36 +0530637 responseReceived = false;
Andrew Jefferya330b2f2023-05-04 14:55:37 +0930638 auto instanceId = instanceIdDb.next(mctp_eid);
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500639 std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) +
640 PLDM_GET_VERSION_REQ_BYTES);
641 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
642 auto rc = encode_get_version_req(instanceId, 0, PLDM_GET_FIRSTPART,
643 PLDM_BASE, request);
644 if (rc != PLDM_SUCCESS)
sampmisr6decfc12021-03-02 11:07:36 +0530645 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600646 error("GetPLDMVersion encode failure. PLDM error code = {RC}", "RC",
647 lg2::hex, rc);
Andrew Jefferya330b2f2023-05-04 14:55:37 +0930648 instanceIdDb.free(mctp_eid, instanceId);
sampmisr6decfc12021-03-02 11:07:36 +0530649 return;
650 }
651
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500652 auto getPLDMVersionHandler = [this](mctp_eid_t /*eid*/,
653 const pldm_msg* response,
654 size_t respMsgLen) {
655 if (response == nullptr || !respMsgLen)
sampmisr6decfc12021-03-02 11:07:36 +0530656 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600657 error(
658 "Failed to receive response for getPLDMVersion command, Host seems to be off");
sampmisr6decfc12021-03-02 11:07:36 +0530659 return;
660 }
Riya Dixit49cfb132023-03-02 04:26:53 -0600661 info("Getting the response. PLDM RC = {RC}", "RC", lg2::hex,
662 static_cast<uint16_t>(response->payload[0]));
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500663 this->responseReceived = true;
664 getHostPDR();
sampmisr6decfc12021-03-02 11:07:36 +0530665 };
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500666 rc = handler->registerRequest(mctp_eid, instanceId, PLDM_BASE,
667 PLDM_GET_PLDM_VERSION, std::move(requestMsg),
668 std::move(getPLDMVersionHandler));
669 if (rc)
sampmisr6decfc12021-03-02 11:07:36 +0530670 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600671 error("Failed to discover Host state. Assuming Host as off");
sampmisr6decfc12021-03-02 11:07:36 +0530672 }
673}
674
675bool HostPDRHandler::isHostUp()
676{
677 return responseReceived;
678}
679
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530680void HostPDRHandler::setHostSensorState(const PDRList& stateSensorPDRs)
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600681{
682 for (const auto& stateSensorPDR : stateSensorPDRs)
683 {
684 auto pdr = reinterpret_cast<const pldm_state_sensor_pdr*>(
685 stateSensorPDR.data());
686
687 if (!pdr)
688 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600689 error("Failed to get State sensor PDR");
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600690 pldm::utils::reportError(
691 "xyz.openbmc_project.bmc.pldm.InternalFailure");
692 return;
693 }
694
695 uint16_t sensorId = pdr->sensor_id;
696
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530697 for (const auto& [terminusHandle, terminusInfo] : tlPDRInfo)
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600698 {
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530699 if (terminusHandle == pdr->terminus_handle)
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600700 {
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530701 if (std::get<2>(terminusInfo) == PLDM_TL_PDR_VALID)
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600702 {
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530703 mctp_eid = std::get<1>(terminusInfo);
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600704 }
705
706 bitfield8_t sensorRearm;
707 sensorRearm.byte = 0;
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530708 uint8_t tid = std::get<0>(terminusInfo);
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600709
Andrew Jefferya330b2f2023-05-04 14:55:37 +0930710 auto instanceId = instanceIdDb.next(mctp_eid);
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600711 std::vector<uint8_t> requestMsg(
712 sizeof(pldm_msg_hdr) +
713 PLDM_GET_STATE_SENSOR_READINGS_REQ_BYTES);
714 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
715 auto rc = encode_get_state_sensor_readings_req(
716 instanceId, sensorId, sensorRearm, 0, request);
717
718 if (rc != PLDM_SUCCESS)
719 {
Andrew Jefferya330b2f2023-05-04 14:55:37 +0930720 instanceIdDb.free(mctp_eid, instanceId);
Riya Dixit49cfb132023-03-02 04:26:53 -0600721 error(
722 "Failed to encode_get_state_sensor_readings_req, rc = {RC}",
723 "RC", rc);
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600724 pldm::utils::reportError(
725 "xyz.openbmc_project.bmc.pldm.InternalFailure");
726 return;
727 }
728
Patrick Williams6da4f912023-05-10 07:50:53 -0500729 auto getStateSensorReadingRespHandler =
730 [=, this](mctp_eid_t /*eid*/, const pldm_msg* response,
731 size_t respMsgLen) {
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600732 if (response == nullptr || !respMsgLen)
733 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600734 error(
735 "Failed to receive response for getStateSensorReading command");
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600736 return;
737 }
738 std::array<get_sensor_state_field, 8> stateField{};
739 uint8_t completionCode = 0;
740 uint8_t comp_sensor_count = 0;
741
742 auto rc = decode_get_state_sensor_readings_resp(
743 response, respMsgLen, &completionCode,
744 &comp_sensor_count, stateField.data());
745
746 if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS)
747 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600748 error(
749 "Failed to decode_get_state_sensor_readings_resp, rc = {RC} cc = {CC}",
750 "RC", rc, "CC",
751 static_cast<unsigned>(completionCode));
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600752 pldm::utils::reportError(
753 "xyz.openbmc_project.bmc.pldm.InternalFailure");
754 }
755
756 uint8_t eventState;
757 uint8_t previousEventState;
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600758
RIYA DIXITbb5fda42022-09-27 06:48:08 -0500759 for (uint8_t sensorOffset = 0;
760 sensorOffset < comp_sensor_count; sensorOffset++)
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600761 {
RIYA DIXITbb5fda42022-09-27 06:48:08 -0500762 eventState = stateField[sensorOffset].present_state;
763 previousEventState =
764 stateField[sensorOffset].previous_state;
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600765
766 emitStateSensorEventSignal(tid, sensorId, sensorOffset,
767 eventState,
768 previousEventState);
769
770 SensorEntry sensorEntry{tid, sensorId};
771
772 pldm::pdr::EntityInfo entityInfo{};
773 pldm::pdr::CompositeSensorStates
774 compositeSensorStates{};
775
776 try
777 {
778 std::tie(entityInfo, compositeSensorStates) =
779 lookupSensorInfo(sensorEntry);
780 }
781 catch (const std::out_of_range& e)
782 {
783 try
784 {
785 sensorEntry.terminusID = PLDM_TID_RESERVED;
786 std::tie(entityInfo, compositeSensorStates) =
787 lookupSensorInfo(sensorEntry);
788 }
789 catch (const std::out_of_range& e)
790 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600791 error("No mapping for the events");
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600792 }
793 }
794
795 if (sensorOffset > compositeSensorStates.size())
796 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600797 error("Error Invalid data, Invalid sensor offset");
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600798 return;
799 }
800
801 const auto& possibleStates =
802 compositeSensorStates[sensorOffset];
803 if (possibleStates.find(eventState) ==
804 possibleStates.end())
805 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600806 error("Error invalid_data, Invalid event state");
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600807 return;
808 }
Patrick Williams6da4f912023-05-10 07:50:53 -0500809 const auto& [containerId, entityType,
810 entityInstance] = entityInfo;
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600811 pldm::responder::events::StateSensorEntry
812 stateSensorEntry{containerId, entityType,
813 entityInstance, sensorOffset};
814 handleStateSensorEvent(stateSensorEntry, eventState);
815 }
816 };
817
818 rc = handler->registerRequest(
819 mctp_eid, instanceId, PLDM_PLATFORM,
820 PLDM_GET_STATE_SENSOR_READINGS, std::move(requestMsg),
821 std::move(getStateSensorReadingRespHandler));
822
823 if (rc != PLDM_SUCCESS)
824 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600825 error(
826 "Failed to send request to get State sensor reading on Host");
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600827 }
828 }
829 }
830 }
831}
George Liu682ee182020-12-25 15:24:33 +0800832
833void HostPDRHandler::getFRURecordTableMetadataByRemote(
834 const PDRList& fruRecordSetPDRs)
835{
836 auto instanceId = instanceIdDb.next(mctp_eid);
837 std::vector<uint8_t> requestMsg(
838 sizeof(pldm_msg_hdr) + PLDM_GET_FRU_RECORD_TABLE_METADATA_REQ_BYTES);
839
840 // GetFruRecordTableMetadata
841 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
842 auto rc = encode_get_fru_record_table_metadata_req(
843 instanceId, request, requestMsg.size() - sizeof(pldm_msg_hdr));
844 if (rc != PLDM_SUCCESS)
845 {
846 instanceIdDb.free(mctp_eid, instanceId);
847 lg2::error(
848 "Failed to encode_get_fru_record_table_metadata_req, rc = {RC}",
849 "RC", lg2::hex, rc);
850 return;
851 }
852
853 auto getFruRecordTableMetadataResponseHandler =
854 [this, fruRecordSetPDRs](mctp_eid_t /*eid*/, const pldm_msg* response,
855 size_t respMsgLen) {
856 if (response == nullptr || !respMsgLen)
857 {
858 lg2::error(
859 "Failed to receive response for the Get FRU Record Table Metadata");
860 return;
861 }
862
863 uint8_t cc = 0;
864 uint8_t fru_data_major_version, fru_data_minor_version;
865 uint32_t fru_table_maximum_size, fru_table_length;
866 uint16_t total_record_set_identifiers;
867 uint16_t total;
868 uint32_t checksum;
869
870 auto rc = decode_get_fru_record_table_metadata_resp(
871 response, respMsgLen, &cc, &fru_data_major_version,
872 &fru_data_minor_version, &fru_table_maximum_size, &fru_table_length,
873 &total_record_set_identifiers, &total, &checksum);
874
875 if (rc != PLDM_SUCCESS || cc != PLDM_SUCCESS)
876 {
877 lg2::error(
878 "Faile to decode get fru record table metadata resp, Message Error: {RC}, cc: {CC}",
879 "RC", lg2::hex, rc, "CC", cc);
880 return;
881 }
882
883 // pass total to getFRURecordTableByRemote
884 this->getFRURecordTableByRemote(fruRecordSetPDRs, total);
885 };
886
887 rc = handler->registerRequest(
888 mctp_eid, instanceId, PLDM_FRU, PLDM_GET_FRU_RECORD_TABLE_METADATA,
889 std::move(requestMsg),
890 std::move(getFruRecordTableMetadataResponseHandler));
891 if (rc != PLDM_SUCCESS)
892 {
893 lg2::error("Failed to send the the Set State Effecter States request");
894 }
895
896 return;
897}
898
899void HostPDRHandler::getFRURecordTableByRemote(const PDRList& fruRecordSetPDRs,
900 uint16_t totalTableRecords)
901{
902 fruRecordData.clear();
903
904 if (!totalTableRecords)
905 {
906 lg2::error("Failed to get fru record table");
907 return;
908 }
909
910 auto instanceId = instanceIdDb.next(mctp_eid);
911 std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) +
912 PLDM_GET_FRU_RECORD_TABLE_REQ_BYTES);
913
914 // send the getFruRecordTable command
915 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
916 auto rc = encode_get_fru_record_table_req(
917 instanceId, 0, PLDM_GET_FIRSTPART, request,
918 requestMsg.size() - sizeof(pldm_msg_hdr));
919 if (rc != PLDM_SUCCESS)
920 {
921 instanceIdDb.free(mctp_eid, instanceId);
922 lg2::error("Failed to encode_get_fru_record_table_req, rc = {RC}", "RC",
923 lg2::hex, rc);
924 return;
925 }
926
927 auto getFruRecordTableResponseHandler =
928 [totalTableRecords, this, fruRecordSetPDRs](
929 mctp_eid_t /*eid*/, const pldm_msg* response, size_t respMsgLen) {
930 if (response == nullptr || !respMsgLen)
931 {
932 lg2::error(
933 "Failed to receive response for the Get FRU Record Table");
934 return;
935 }
936
937 uint8_t cc = 0;
938 uint32_t next_data_transfer_handle = 0;
939 uint8_t transfer_flag = 0;
940 size_t fru_record_table_length = 0;
941 std::vector<uint8_t> fru_record_table_data(respMsgLen -
942 sizeof(pldm_msg_hdr));
943 auto responsePtr = reinterpret_cast<const struct pldm_msg*>(response);
944 auto rc = decode_get_fru_record_table_resp(
945 responsePtr, respMsgLen - sizeof(pldm_msg_hdr), &cc,
946 &next_data_transfer_handle, &transfer_flag,
947 fru_record_table_data.data(), &fru_record_table_length);
948
949 if (rc != PLDM_SUCCESS || cc != PLDM_SUCCESS)
950 {
951 lg2::error(
952 "Failed to decode get fru record table resp, Message Error: {RC}, cc: {CC}",
953 "RC", lg2::hex, rc, "CC", cc);
954 return;
955 }
956
957 fruRecordData = responder::pdr_utils::parseFruRecordTable(
958 fru_record_table_data.data(), fru_record_table_length);
959
960 if (totalTableRecords != fruRecordData.size())
961 {
962 fruRecordData.clear();
963
964 lg2::error("failed to parse fru recrod data format.");
965 return;
966 }
967
968 this->setFRUDataOnDBus(fruRecordSetPDRs, fruRecordData);
969 };
970
971 rc = handler->registerRequest(
972 mctp_eid, instanceId, PLDM_FRU, PLDM_GET_FRU_RECORD_TABLE,
973 std::move(requestMsg), std::move(getFruRecordTableResponseHandler));
974 if (rc != PLDM_SUCCESS)
975 {
976 lg2::error("Failed to send the the Set State Effecter States request");
977 }
978}
979
980std::optional<uint16_t> HostPDRHandler::getRSI(const PDRList& fruRecordSetPDRs,
981 const pldm_entity& entity)
982{
983 for (const auto& pdr : fruRecordSetPDRs)
984 {
985 auto fruPdr = reinterpret_cast<const pldm_pdr_fru_record_set*>(
986 const_cast<uint8_t*>(pdr.data()) + sizeof(pldm_pdr_hdr));
987
988 if (fruPdr->entity_type == entity.entity_type &&
989 fruPdr->entity_instance_num == entity.entity_instance_num)
990 {
991 return fruPdr->fru_rsi;
992 }
993 }
994
995 return std::nullopt;
996}
997
998void HostPDRHandler::setFRUDataOnDBus(
999 const PDRList& fruRecordSetPDRs,
1000 const std::vector<responder::pdr_utils::FruRecordDataFormat>& fruRecordData)
1001{
1002 for (const auto& entity : objPathMap)
1003 {
1004 pldm_entity node = pldm_entity_extract(entity.second);
1005 auto fruRSI = getRSI(fruRecordSetPDRs, node);
1006
1007 for (const auto& data : fruRecordData)
1008 {
1009 if (!fruRSI || *fruRSI != data.fruRSI)
1010 {
1011 continue;
1012 }
1013
1014 if (data.fruRecType == PLDM_FRU_RECORD_TYPE_OEM)
1015 {
1016 for (const auto& tlv : data.fruTLV)
1017 {
1018 if (tlv.fruFieldType ==
1019 PLDM_OEM_FRU_FIELD_TYPE_LOCATION_CODE)
1020 {
1021 CustomDBus::getCustomDBus().setLocationCode(
1022 entity.first,
1023 std::string(reinterpret_cast<const char*>(
1024 tlv.fruFieldValue.data()),
1025 tlv.fruFieldLen));
1026 }
1027 }
1028 }
1029 }
1030 }
1031}
1032void HostPDRHandler::createDbusObjects(const PDRList& fruRecordSetPDRs)
1033{
1034 // TODO: Creating and Refreshing dbus hosted by remote PLDM entity Fru PDRs
1035
1036 getFRURecordTableMetadataByRemote(fruRecordSetPDRs);
1037}
1038
Pavithra Barithaya51efaf82020-04-02 02:42:27 -05001039} // namespace pldm