blob: f201965a942af5d94f7c63531268f5d74a1fb74f [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
Andrew Jeffery27a022c2022-08-10 23:12:49 +09305#include "libpldm/pldm.h"
George Liu6492f522020-06-16 10:34:05 +08006
Pavithra Barithayae8beb892020-04-14 23:24:25 -05007#include <assert.h>
8
Deepak Kodihalli87514cc2020-04-16 09:08:38 -05009#include <nlohmann/json.hpp>
sampmisr6decfc12021-03-02 11:07:36 +053010#include <sdeventplus/clock.hpp>
11#include <sdeventplus/exception.hpp>
12#include <sdeventplus/source/io.hpp>
13#include <sdeventplus/source/time.hpp>
Deepak Kodihalli87514cc2020-04-16 09:08:38 -050014
George Liu6492f522020-06-16 10:34:05 +080015#include <fstream>
Pavithra Barithaya51efaf82020-04-02 02:42:27 -050016
17namespace pldm
18{
Brad Bishop5079ac42021-08-19 18:35:06 -040019using namespace pldm::dbus_api;
20using namespace pldm::responder::events;
Deepak Kodihalli6b1d1ca2020-04-27 07:24:51 -050021using namespace pldm::utils;
22using namespace sdbusplus::bus::match::rules;
Deepak Kodihalli87514cc2020-04-16 09:08:38 -050023using Json = nlohmann::json;
24namespace fs = std::filesystem;
25constexpr auto fruJson = "host_frus.json";
26const Json emptyJson{};
27const std::vector<Json> emptyJsonList{};
28
Manojkiran Eda3ca40452021-10-04 22:51:37 +053029template <typename T>
30uint16_t extractTerminusHandle(std::vector<uint8_t>& pdr)
31{
32 T* var = nullptr;
33 if (std::is_same<T, pldm_pdr_fru_record_set>::value)
34 {
35 var = (T*)(pdr.data() + sizeof(pldm_pdr_hdr));
36 }
37 else
38 {
39 var = (T*)(pdr.data());
40 }
41 if (var != nullptr)
42 {
43 return var->terminus_handle;
44 }
45 return TERMINUS_HANDLE;
46}
47
Tom Joseph74f27c72021-05-16 07:58:53 -070048HostPDRHandler::HostPDRHandler(
49 int mctp_fd, uint8_t mctp_eid, sdeventplus::Event& event, pldm_pdr* repo,
50 const std::string& eventsJsonsDir, pldm_entity_association_tree* entityTree,
51 pldm_entity_association_tree* bmcEntityTree, Requester& requester,
Tom Josephe5268cd2021-09-07 13:04:03 +053052 pldm::requester::Handler<pldm::requester::Request>* handler) :
Deepak Kodihalli87514cc2020-04-16 09:08:38 -050053 mctp_fd(mctp_fd),
Pavithra Barithaya3aec9972020-12-14 01:55:44 -060054 mctp_eid(mctp_eid), event(event), repo(repo),
55 stateSensorHandler(eventsJsonsDir), entityTree(entityTree),
Tom Josephe5268cd2021-09-07 13:04:03 +053056 bmcEntityTree(bmcEntityTree), requester(requester), handler(handler)
Deepak Kodihalli87514cc2020-04-16 09:08:38 -050057{
58 fs::path hostFruJson(fs::path(HOST_JSONS_DIR) / fruJson);
59 if (fs::exists(hostFruJson))
60 {
Pavithra Barithayae8beb892020-04-14 23:24:25 -050061 // Note parent entities for entities sent down by the host firmware.
62 // This will enable a merge of entity associations.
Deepak Kodihalli87514cc2020-04-16 09:08:38 -050063 try
64 {
65 std::ifstream jsonFile(hostFruJson);
66 auto data = Json::parse(jsonFile, nullptr, false);
67 if (data.is_discarded())
68 {
69 std::cerr << "Parsing Host FRU json file failed" << std::endl;
70 }
71 else
72 {
73 auto entities = data.value("entities", emptyJsonList);
74 for (auto& entity : entities)
75 {
76 EntityType entityType = entity.value("entity_type", 0);
77 auto parent = entity.value("parent", emptyJson);
78 pldm_entity p{};
79 p.entity_type = parent.value("entity_type", 0);
80 p.entity_instance_num = parent.value("entity_instance", 0);
81 parents.emplace(entityType, std::move(p));
82 }
83 }
84 }
85 catch (const std::exception& e)
86 {
87 std::cerr << "Parsing Host FRU json file failed, exception = "
88 << e.what() << std::endl;
89 }
90 }
Deepak Kodihalli6b1d1ca2020-04-27 07:24:51 -050091
Patrick Williams84b790c2022-07-22 19:26:56 -050092 hostOffMatch = std::make_unique<sdbusplus::bus::match_t>(
Deepak Kodihalli6b1d1ca2020-04-27 07:24:51 -050093 pldm::utils::DBusHandler::getBus(),
94 propertiesChanged("/xyz/openbmc_project/state/host0",
95 "xyz.openbmc_project.State.Host"),
Patrick Williams84b790c2022-07-22 19:26:56 -050096 [this, repo, entityTree, bmcEntityTree](sdbusplus::message_t& msg) {
Deepak Kodihalli6b1d1ca2020-04-27 07:24:51 -050097 DbusChangedProps props{};
98 std::string intf;
99 msg.read(intf, props);
100 const auto itr = props.find("CurrentHostState");
101 if (itr != props.end())
102 {
103 PropertyValue value = itr->second;
104 auto propVal = std::get<std::string>(value);
105 if (propVal == "xyz.openbmc_project.State.Host.HostState.Off")
106 {
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530107 // Delete all the remote terminus information
Manojkiran Eda8fee19a2021-11-15 12:07:44 +0530108 std::erase_if(tlPDRInfo, [](const auto& item) {
109 auto const& [key, value] = item;
110 return key != TERMINUS_HANDLE;
111 });
Deepak Kodihalli6b1d1ca2020-04-27 07:24:51 -0500112 pldm_pdr_remove_remote_pdrs(repo);
Sampa Misrac073a202021-05-08 10:56:05 -0500113 pldm_entity_association_tree_destroy_root(entityTree);
114 pldm_entity_association_tree_copy_root(bmcEntityTree,
115 entityTree);
Tom Josephb4268602020-04-17 17:20:45 +0530116 this->sensorMap.clear();
Pavithra Barithaya23025b92021-09-28 05:22:52 -0500117 this->responseReceived = false;
Deepak Kodihalli6b1d1ca2020-04-27 07:24:51 -0500118 }
119 }
120 });
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500121}
122
Deepak Kodihalli7246e0c2020-07-08 06:40:18 -0500123void HostPDRHandler::fetchPDR(PDRRecordHandles&& recordHandles)
Pavithra Barithaya51efaf82020-04-02 02:42:27 -0500124{
Deepak Kodihalli8cb6f662020-04-10 02:55:43 -0500125 pdrRecordHandles.clear();
Pavithra Barithayaae5c97e2022-08-29 02:57:59 -0500126 modifiedPDRRecordHandles.clear();
127
128 if (isHostPdrModified)
129 {
130 modifiedPDRRecordHandles = std::move(recordHandles);
131 }
132 else
133 {
134 pdrRecordHandles = std::move(recordHandles);
135 }
Deepak Kodihalli8cb6f662020-04-10 02:55:43 -0500136
137 // Defer the actual fetch of PDRs from the host (by queuing the call on the
138 // main event loop). That way, we can respond to the platform event msg from
139 // the host firmware.
140 pdrFetchEvent = std::make_unique<sdeventplus::source::Defer>(
141 event, std::bind(std::mem_fn(&HostPDRHandler::_fetchPDR), this,
142 std::placeholders::_1));
143}
144
145void HostPDRHandler::_fetchPDR(sdeventplus::source::EventBase& /*source*/)
146{
Sampa Misrac0c79482021-06-02 08:01:54 -0500147 getHostPDR();
148}
149
150void HostPDRHandler::getHostPDR(uint32_t nextRecordHandle)
151{
Deepak Kodihalli8cb6f662020-04-10 02:55:43 -0500152 pdrFetchEvent.reset();
153
Pavithra Barithaya51efaf82020-04-02 02:42:27 -0500154 std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) +
155 PLDM_GET_PDR_REQ_BYTES);
156 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
Deepak Kodihalli7246e0c2020-07-08 06:40:18 -0500157 uint32_t recordHandle{};
Pavithra Barithayaae5c97e2022-08-29 02:57:59 -0500158 if (!nextRecordHandle && (!modifiedPDRRecordHandles.empty()) &&
159 isHostPdrModified)
Deepak Kodihalli7246e0c2020-07-08 06:40:18 -0500160 {
Pavithra Barithayaae5c97e2022-08-29 02:57:59 -0500161 recordHandle = modifiedPDRRecordHandles.front();
162 modifiedPDRRecordHandles.pop_front();
163 }
164 else if (!nextRecordHandle && (!pdrRecordHandles.empty()))
165 {
166 recordHandle = pdrRecordHandles.front();
167 pdrRecordHandles.pop_front();
Sampa Misrac0c79482021-06-02 08:01:54 -0500168 }
169 else
170 {
171 recordHandle = nextRecordHandle;
172 }
173 auto instanceId = requester.getInstanceId(mctp_eid);
174
175 auto rc =
176 encode_get_pdr_req(instanceId, recordHandle, 0, PLDM_GET_FIRSTPART,
177 UINT16_MAX, 0, request, PLDM_GET_PDR_REQ_BYTES);
178 if (rc != PLDM_SUCCESS)
179 {
180 requester.markFree(mctp_eid, instanceId);
181 std::cerr << "Failed to encode_get_pdr_req, rc = " << rc << std::endl;
182 return;
183 }
Deepak Kodihalli7246e0c2020-07-08 06:40:18 -0500184
Sampa Misrac0c79482021-06-02 08:01:54 -0500185 rc = handler->registerRequest(
186 mctp_eid, instanceId, PLDM_PLATFORM, PLDM_GET_PDR,
187 std::move(requestMsg),
188 std::move(std::bind_front(&HostPDRHandler::processHostPDRs, this)));
189 if (rc)
Pavithra Barithaya51efaf82020-04-02 02:42:27 -0500190 {
Sampa Misrac0c79482021-06-02 08:01:54 -0500191 std::cerr << "Failed to send the GetPDR request to Host \n";
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500192 }
Pavithra Barithaya51efaf82020-04-02 02:42:27 -0500193}
194
Pavithra Barithaya3aec9972020-12-14 01:55:44 -0600195int HostPDRHandler::handleStateSensorEvent(const StateSensorEntry& entry,
196 pdr::EventState state)
197{
198 auto rc = stateSensorHandler.eventAction(entry, state);
199 if (rc != PLDM_SUCCESS)
200 {
201 std::cerr << "Failed to fetch and update D-bus property, rc = " << rc
202 << std::endl;
203 return rc;
204 }
205 return PLDM_SUCCESS;
206}
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500207bool HostPDRHandler::getParent(EntityType type, pldm_entity& parent)
208{
209 auto found = parents.find(type);
210 if (found != parents.end())
211 {
212 parent.entity_type = found->second.entity_type;
213 parent.entity_instance_num = found->second.entity_instance_num;
214 return true;
215 }
216
217 return false;
218}
219
220void HostPDRHandler::mergeEntityAssociations(const std::vector<uint8_t>& pdr)
221{
222 size_t numEntities{};
223 pldm_entity* entities = nullptr;
224 bool merged = false;
225 auto entityPdr = reinterpret_cast<pldm_pdr_entity_association*>(
226 const_cast<uint8_t*>(pdr.data()) + sizeof(pldm_pdr_hdr));
227
228 pldm_entity_association_pdr_extract(pdr.data(), pdr.size(), &numEntities,
229 &entities);
230 for (size_t i = 0; i < numEntities; ++i)
231 {
232 pldm_entity parent{};
233 if (getParent(entities[i].entity_type, parent))
234 {
235 auto node = pldm_entity_association_tree_find(entityTree, &parent);
236 if (node)
237 {
George Liu64a8f0f2021-06-12 10:56:11 +0800238 pldm_entity_association_tree_add(entityTree, &entities[i],
239 0xFFFF, node,
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500240 entityPdr->association_type);
241 merged = true;
242 }
243 }
244 }
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500245
246 if (merged)
247 {
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500248 // Update our PDR repo with the merged entity association PDRs
Sampa Misra719ed392021-06-04 05:15:13 -0500249 pldm_entity_node* node = nullptr;
250 pldm_find_entity_ref_in_tree(entityTree, entities[0], &node);
251 if (node == nullptr)
252 {
253 std::cerr
254 << "\ncould not find referrence of the entity in the tree \n";
255 }
256 else
257 {
Manojkiran Eda3ca40452021-10-04 22:51:37 +0530258 pldm_entity_association_pdr_add_from_node(
259 node, repo, &entities, numEntities, true, TERMINUS_HANDLE);
Sampa Misra719ed392021-06-04 05:15:13 -0500260 }
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500261 }
Sampa Misra719ed392021-06-04 05:15:13 -0500262 free(entities);
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500263}
264
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500265void HostPDRHandler::sendPDRRepositoryChgEvent(std::vector<uint8_t>&& pdrTypes,
266 uint8_t eventDataFormat)
267{
268 assert(eventDataFormat == FORMAT_IS_PDR_HANDLES);
269
270 // Extract from the PDR repo record handles of PDRs we want the host
271 // to pull up.
272 std::vector<uint8_t> eventDataOps{PLDM_RECORDS_ADDED};
273 std::vector<uint8_t> numsOfChangeEntries(1);
274 std::vector<std::vector<ChangeEntry>> changeEntries(
275 numsOfChangeEntries.size());
276 for (auto pdrType : pdrTypes)
277 {
278 const pldm_pdr_record* record{};
279 do
280 {
281 record = pldm_pdr_find_record_by_type(repo, pdrType, record,
282 nullptr, nullptr);
283 if (record && pldm_pdr_record_is_remote(record))
284 {
285 changeEntries[0].push_back(
286 pldm_pdr_get_record_handle(repo, record));
287 }
288 } while (record);
289 }
290 if (changeEntries.empty())
291 {
292 return;
293 }
294 numsOfChangeEntries[0] = changeEntries[0].size();
295
296 // Encode PLDM platform event msg to indicate a PDR repo change.
297 size_t maxSize = PLDM_PDR_REPOSITORY_CHG_EVENT_MIN_LENGTH +
298 PLDM_PDR_REPOSITORY_CHANGE_RECORD_MIN_LENGTH +
299 changeEntries[0].size() * sizeof(uint32_t);
300 std::vector<uint8_t> eventDataVec{};
301 eventDataVec.resize(maxSize);
302 auto eventData =
303 reinterpret_cast<struct pldm_pdr_repository_chg_event_data*>(
304 eventDataVec.data());
305 size_t actualSize{};
306 auto firstEntry = changeEntries[0].data();
307 auto rc = encode_pldm_pdr_repository_chg_event_data(
308 eventDataFormat, 1, eventDataOps.data(), numsOfChangeEntries.data(),
309 &firstEntry, eventData, &actualSize, maxSize);
310 if (rc != PLDM_SUCCESS)
311 {
312 std::cerr
313 << "Failed to encode_pldm_pdr_repository_chg_event_data, rc = "
314 << rc << std::endl;
315 return;
316 }
317 auto instanceId = requester.getInstanceId(mctp_eid);
318 std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) +
319 PLDM_PLATFORM_EVENT_MESSAGE_MIN_REQ_BYTES +
320 actualSize);
321 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
322 rc = encode_platform_event_message_req(
323 instanceId, 1, 0, PLDM_PDR_REPOSITORY_CHG_EVENT, eventDataVec.data(),
Christian Geddes3bdb3c22020-05-01 14:55:39 -0500324 actualSize, request,
325 actualSize + PLDM_PLATFORM_EVENT_MESSAGE_MIN_REQ_BYTES);
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500326 if (rc != PLDM_SUCCESS)
327 {
328 requester.markFree(mctp_eid, instanceId);
329 std::cerr << "Failed to encode_platform_event_message_req, rc = " << rc
330 << std::endl;
331 return;
332 }
333
Tom Joseph74f27c72021-05-16 07:58:53 -0700334 auto platformEventMessageResponseHandler = [](mctp_eid_t /*eid*/,
335 const pldm_msg* response,
336 size_t respMsgLen) {
337 if (response == nullptr || !respMsgLen)
338 {
339 std::cerr << "Failed to receive response for the PDR repository "
340 "changed event"
341 << "\n";
342 return;
343 }
344
345 uint8_t completionCode{};
346 uint8_t status{};
347 auto responsePtr = reinterpret_cast<const struct pldm_msg*>(response);
Pavithra Barithaya54b5a562021-09-27 06:07:10 -0500348 auto rc = decode_platform_event_message_resp(responsePtr, respMsgLen,
349 &completionCode, &status);
Sampa Misrac0c79482021-06-02 08:01:54 -0500350 if (rc || completionCode)
Tom Joseph74f27c72021-05-16 07:58:53 -0700351 {
352 std::cerr << "Failed to decode_platform_event_message_resp: "
353 << "rc=" << rc
354 << ", cc=" << static_cast<unsigned>(completionCode)
355 << std::endl;
356 }
357 };
358
Sampa Misrac0c79482021-06-02 08:01:54 -0500359 rc = handler->registerRequest(
Sampa Misra626c5652021-08-11 10:28:48 -0500360 mctp_eid, instanceId, PLDM_PLATFORM, PLDM_PLATFORM_EVENT_MESSAGE,
Tom Joseph74f27c72021-05-16 07:58:53 -0700361 std::move(requestMsg), std::move(platformEventMessageResponseHandler));
Sampa Misrac0c79482021-06-02 08:01:54 -0500362 if (rc)
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500363 {
Tom Joseph74f27c72021-05-16 07:58:53 -0700364 std::cerr << "Failed to send the PDR repository changed event request"
365 << "\n";
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500366 }
367}
368
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530369void HostPDRHandler::parseStateSensorPDRs(const PDRList& stateSensorPDRs)
Sampa Misra868c8792020-05-26 03:12:13 -0500370{
371 for (const auto& pdr : stateSensorPDRs)
372 {
373 SensorEntry sensorEntry{};
374 const auto& [terminusHandle, sensorID, sensorInfo] =
375 responder::pdr_utils::parseStateSensorPDR(pdr);
376 sensorEntry.sensorID = sensorID;
377 try
378 {
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530379 sensorEntry.terminusID = std::get<0>(tlPDRInfo.at(terminusHandle));
Sampa Misra868c8792020-05-26 03:12:13 -0500380 }
381 // If there is no mapping for terminusHandle assign the reserved TID
382 // value of 0xFF to indicate that.
383 catch (const std::out_of_range& e)
384 {
385 sensorEntry.terminusID = PLDM_TID_RESERVED;
386 }
387 sensorMap.emplace(sensorEntry, std::move(sensorInfo));
388 }
389}
390
Sampa Misrac0c79482021-06-02 08:01:54 -0500391void HostPDRHandler::processHostPDRs(mctp_eid_t /*eid*/,
392 const pldm_msg* response,
393 size_t respMsgLen)
394{
395 static bool merged = false;
396 static PDRList stateSensorPDRs{};
Sampa Misrac0c79482021-06-02 08:01:54 -0500397 uint32_t nextRecordHandle{};
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600398 uint8_t tlEid = 0;
399 bool tlValid = true;
400 uint32_t rh = 0;
401 uint16_t terminusHandle = 0;
Manojkiran Eda3ca40452021-10-04 22:51:37 +0530402 uint16_t pdrTerminusHandle = 0;
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600403 uint8_t tid = 0;
404
Sampa Misrac0c79482021-06-02 08:01:54 -0500405 uint8_t completionCode{};
406 uint32_t nextDataTransferHandle{};
407 uint8_t transferFlag{};
408 uint16_t respCount{};
409 uint8_t transferCRC{};
410 if (response == nullptr || !respMsgLen)
411 {
412 std::cerr << "Failed to receive response for the GetPDR"
413 " command \n";
414 return;
415 }
416
417 auto rc = decode_get_pdr_resp(
418 response, respMsgLen /*- sizeof(pldm_msg_hdr)*/, &completionCode,
419 &nextRecordHandle, &nextDataTransferHandle, &transferFlag, &respCount,
420 nullptr, 0, &transferCRC);
421 std::vector<uint8_t> responsePDRMsg;
422 responsePDRMsg.resize(respMsgLen + sizeof(pldm_msg_hdr));
423 memcpy(responsePDRMsg.data(), response, respMsgLen + sizeof(pldm_msg_hdr));
Sampa Misrac0c79482021-06-02 08:01:54 -0500424 if (rc != PLDM_SUCCESS)
425 {
426 std::cerr << "Failed to decode_get_pdr_resp, rc = " << rc << std::endl;
427 return;
428 }
429 else
430 {
431 std::vector<uint8_t> pdr(respCount, 0);
432 rc = decode_get_pdr_resp(response, respMsgLen, &completionCode,
433 &nextRecordHandle, &nextDataTransferHandle,
434 &transferFlag, &respCount, pdr.data(),
435 respCount, &transferCRC);
436 if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS)
437 {
438 std::cerr << "Failed to decode_get_pdr_resp: "
439 << "rc=" << rc
440 << ", cc=" << static_cast<unsigned>(completionCode)
441 << std::endl;
442 return;
443 }
444 else
445 {
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600446 // when nextRecordHandle is 0, we need the recordHandle of the last
447 // PDR and not 0-1.
448 if (!nextRecordHandle)
449 {
450 rh = nextRecordHandle;
451 }
452 else
453 {
454 rh = nextRecordHandle - 1;
455 }
456
Sampa Misrac0c79482021-06-02 08:01:54 -0500457 auto pdrHdr = reinterpret_cast<pldm_pdr_hdr*>(pdr.data());
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600458 if (!rh)
459 {
460 rh = pdrHdr->record_handle;
461 }
462
Sampa Misrac0c79482021-06-02 08:01:54 -0500463 if (pdrHdr->type == PLDM_PDR_ENTITY_ASSOCIATION)
464 {
465 this->mergeEntityAssociations(pdr);
466 merged = true;
467 }
468 else
469 {
470 if (pdrHdr->type == PLDM_TERMINUS_LOCATOR_PDR)
471 {
Manojkiran Eda3ca40452021-10-04 22:51:37 +0530472 pdrTerminusHandle =
473 extractTerminusHandle<pldm_terminus_locator_pdr>(pdr);
Sampa Misrac0c79482021-06-02 08:01:54 -0500474 auto tlpdr =
475 reinterpret_cast<const pldm_terminus_locator_pdr*>(
476 pdr.data());
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600477
478 terminusHandle = tlpdr->terminus_handle;
479 tid = tlpdr->tid;
480 auto terminus_locator_type = tlpdr->terminus_locator_type;
481 if (terminus_locator_type ==
482 PLDM_TERMINUS_LOCATOR_TYPE_MCTP_EID)
483 {
484 auto locatorValue = reinterpret_cast<
485 const pldm_terminus_locator_type_mctp_eid*>(
486 tlpdr->terminus_locator_value);
487 tlEid = static_cast<uint8_t>(locatorValue->eid);
488 }
489 if (tlpdr->validity == 0)
490 {
491 tlValid = false;
492 }
Pavithra Barithaya52aad392022-08-02 04:18:52 -0500493 for (const auto& terminusMap : tlPDRInfo)
494 {
495 if ((terminusHandle == (terminusMap.first)) &&
496 (get<1>(terminusMap.second) == tlEid) &&
497 (get<2>(terminusMap.second) == tlpdr->validity))
498 {
499 // TL PDR already present with same validity don't
500 // add the PDR to the repo just return
501 return;
502 }
503 }
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530504 tlPDRInfo.insert_or_assign(
505 tlpdr->terminus_handle,
506 std::make_tuple(tlpdr->tid, tlEid, tlpdr->validity));
Sampa Misrac0c79482021-06-02 08:01:54 -0500507 }
508 else if (pdrHdr->type == PLDM_STATE_SENSOR_PDR)
509 {
Manojkiran Eda3ca40452021-10-04 22:51:37 +0530510 pdrTerminusHandle =
511 extractTerminusHandle<pldm_state_sensor_pdr>(pdr);
Sampa Misrac0c79482021-06-02 08:01:54 -0500512 stateSensorPDRs.emplace_back(pdr);
513 }
Manojkiran Eda3ca40452021-10-04 22:51:37 +0530514 else if (pdrHdr->type == PLDM_PDR_FRU_RECORD_SET)
515 {
516 pdrTerminusHandle =
517 extractTerminusHandle<pldm_pdr_fru_record_set>(pdr);
518 }
519 else if (pdrHdr->type == PLDM_STATE_EFFECTER_PDR)
520 {
521 pdrTerminusHandle =
522 extractTerminusHandle<pldm_state_effecter_pdr>(pdr);
523 }
524 else if (pdrHdr->type == PLDM_NUMERIC_EFFECTER_PDR)
525 {
526 pdrTerminusHandle =
527 extractTerminusHandle<pldm_numeric_effecter_value_pdr>(
528 pdr);
529 }
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600530 // if the TLPDR is invalid update the repo accordingly
531 if (!tlValid)
532 {
533 pldm_pdr_update_TL_pdr(repo, terminusHandle, tid, tlEid,
534 tlValid);
535 }
536 else
537 {
Manojkiran Eda3ca40452021-10-04 22:51:37 +0530538 pldm_pdr_add(repo, pdr.data(), respCount, rh, true,
539 pdrTerminusHandle);
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600540 }
Sampa Misrac0c79482021-06-02 08:01:54 -0500541 }
542 }
543 }
544 if (!nextRecordHandle)
545 {
546 /*received last record*/
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530547 this->parseStateSensorPDRs(stateSensorPDRs);
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600548 if (isHostUp())
549 {
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530550 this->setHostSensorState(stateSensorPDRs);
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600551 }
Sampa Misrac0c79482021-06-02 08:01:54 -0500552 stateSensorPDRs.clear();
Sampa Misrac0c79482021-06-02 08:01:54 -0500553 if (merged)
554 {
555 merged = false;
556 deferredPDRRepoChgEvent =
557 std::make_unique<sdeventplus::source::Defer>(
558 event,
559 std::bind(
560 std::mem_fn((&HostPDRHandler::_processPDRRepoChgEvent)),
561 this, std::placeholders::_1));
562 }
563 }
564 else
565 {
Pavithra Barithayaae5c97e2022-08-29 02:57:59 -0500566 if (modifiedPDRRecordHandles.empty() && isHostPdrModified)
567 {
568 isHostPdrModified = false;
569 }
570 else
571 {
572 deferredFetchPDREvent =
573 std::make_unique<sdeventplus::source::Defer>(
574 event,
575 std::bind(
576 std::mem_fn((&HostPDRHandler::_processFetchPDREvent)),
577 this, nextRecordHandle, std::placeholders::_1));
578 }
Sampa Misrac0c79482021-06-02 08:01:54 -0500579 }
580}
581
582void HostPDRHandler::_processPDRRepoChgEvent(
583 sdeventplus::source::EventBase& /*source */)
584{
585 deferredPDRRepoChgEvent.reset();
586 this->sendPDRRepositoryChgEvent(
587 std::move(std::vector<uint8_t>(1, PLDM_PDR_ENTITY_ASSOCIATION)),
588 FORMAT_IS_PDR_HANDLES);
589}
590
591void HostPDRHandler::_processFetchPDREvent(
592 uint32_t nextRecordHandle, sdeventplus::source::EventBase& /*source */)
593{
594 deferredFetchPDREvent.reset();
595 if (!this->pdrRecordHandles.empty())
596 {
597 nextRecordHandle = this->pdrRecordHandles.front();
598 this->pdrRecordHandles.pop_front();
599 }
Pavithra Barithayaae5c97e2022-08-29 02:57:59 -0500600 if (isHostPdrModified && (!this->modifiedPDRRecordHandles.empty()))
601 {
602 nextRecordHandle = this->modifiedPDRRecordHandles.front();
603 this->modifiedPDRRecordHandles.pop_front();
604 }
Sampa Misrac0c79482021-06-02 08:01:54 -0500605 this->getHostPDR(nextRecordHandle);
606}
607
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500608void HostPDRHandler::setHostFirmwareCondition()
sampmisr6decfc12021-03-02 11:07:36 +0530609{
sampmisr6decfc12021-03-02 11:07:36 +0530610 responseReceived = false;
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500611 auto instanceId = requester.getInstanceId(mctp_eid);
612 std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) +
613 PLDM_GET_VERSION_REQ_BYTES);
614 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
615 auto rc = encode_get_version_req(instanceId, 0, PLDM_GET_FIRSTPART,
616 PLDM_BASE, request);
617 if (rc != PLDM_SUCCESS)
sampmisr6decfc12021-03-02 11:07:36 +0530618 {
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500619 std::cerr << "GetPLDMVersion encode failure. PLDM error code = "
620 << std::hex << std::showbase << rc << "\n";
621 requester.markFree(mctp_eid, instanceId);
sampmisr6decfc12021-03-02 11:07:36 +0530622 return;
623 }
624
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500625 auto getPLDMVersionHandler = [this](mctp_eid_t /*eid*/,
626 const pldm_msg* response,
627 size_t respMsgLen) {
628 if (response == nullptr || !respMsgLen)
sampmisr6decfc12021-03-02 11:07:36 +0530629 {
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500630 std::cerr << "Failed to receive response for "
631 << "getPLDMVersion command, Host seems to be off \n";
sampmisr6decfc12021-03-02 11:07:36 +0530632 return;
633 }
sampmisr6decfc12021-03-02 11:07:36 +0530634 std::cout << "Getting the response. PLDM RC = " << std::hex
635 << std::showbase
636 << static_cast<uint16_t>(response->payload[0]) << "\n";
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500637 this->responseReceived = true;
638 getHostPDR();
sampmisr6decfc12021-03-02 11:07:36 +0530639 };
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500640 rc = handler->registerRequest(mctp_eid, instanceId, PLDM_BASE,
641 PLDM_GET_PLDM_VERSION, std::move(requestMsg),
642 std::move(getPLDMVersionHandler));
643 if (rc)
sampmisr6decfc12021-03-02 11:07:36 +0530644 {
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500645 std::cerr << "Failed to discover Host state. Assuming Host as off \n";
sampmisr6decfc12021-03-02 11:07:36 +0530646 }
647}
648
649bool HostPDRHandler::isHostUp()
650{
651 return responseReceived;
652}
653
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530654void HostPDRHandler::setHostSensorState(const PDRList& stateSensorPDRs)
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600655{
656 for (const auto& stateSensorPDR : stateSensorPDRs)
657 {
658 auto pdr = reinterpret_cast<const pldm_state_sensor_pdr*>(
659 stateSensorPDR.data());
660
661 if (!pdr)
662 {
663 std::cerr << "Failed to get State sensor PDR" << std::endl;
664 pldm::utils::reportError(
665 "xyz.openbmc_project.bmc.pldm.InternalFailure");
666 return;
667 }
668
669 uint16_t sensorId = pdr->sensor_id;
670
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530671 for (const auto& [terminusHandle, terminusInfo] : tlPDRInfo)
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600672 {
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530673 if (terminusHandle == pdr->terminus_handle)
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600674 {
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530675 if (std::get<2>(terminusInfo) == PLDM_TL_PDR_VALID)
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600676 {
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530677 mctp_eid = std::get<1>(terminusInfo);
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600678 }
679
680 bitfield8_t sensorRearm;
681 sensorRearm.byte = 0;
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530682 uint8_t tid = std::get<0>(terminusInfo);
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600683
684 auto instanceId = requester.getInstanceId(mctp_eid);
685 std::vector<uint8_t> requestMsg(
686 sizeof(pldm_msg_hdr) +
687 PLDM_GET_STATE_SENSOR_READINGS_REQ_BYTES);
688 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
689 auto rc = encode_get_state_sensor_readings_req(
690 instanceId, sensorId, sensorRearm, 0, request);
691
692 if (rc != PLDM_SUCCESS)
693 {
694 requester.markFree(mctp_eid, instanceId);
695 std::cerr << "Failed to "
696 "encode_get_state_sensor_readings_req, rc = "
697 << rc << std::endl;
698 pldm::utils::reportError(
699 "xyz.openbmc_project.bmc.pldm.InternalFailure");
700 return;
701 }
702
703 auto getStateSensorReadingRespHandler = [=, this](
704 mctp_eid_t /*eid*/,
705 const pldm_msg*
706 response,
707 size_t respMsgLen) {
708 if (response == nullptr || !respMsgLen)
709 {
710 std::cerr << "Failed to receive response for "
711 "getStateSensorReading command \n";
712 return;
713 }
714 std::array<get_sensor_state_field, 8> stateField{};
715 uint8_t completionCode = 0;
716 uint8_t comp_sensor_count = 0;
717
718 auto rc = decode_get_state_sensor_readings_resp(
719 response, respMsgLen, &completionCode,
720 &comp_sensor_count, stateField.data());
721
722 if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS)
723 {
724 std::cerr
725 << "Failed to "
726 "decode_get_state_sensor_readings_resp, rc = "
727 << rc
728 << " cc=" << static_cast<unsigned>(completionCode)
729 << std::endl;
730 pldm::utils::reportError(
731 "xyz.openbmc_project.bmc.pldm.InternalFailure");
732 }
733
734 uint8_t eventState;
735 uint8_t previousEventState;
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600736
RIYA DIXITbb5fda42022-09-27 06:48:08 -0500737 for (uint8_t sensorOffset = 0;
738 sensorOffset < comp_sensor_count; sensorOffset++)
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600739 {
RIYA DIXITbb5fda42022-09-27 06:48:08 -0500740 eventState = stateField[sensorOffset].present_state;
741 previousEventState =
742 stateField[sensorOffset].previous_state;
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600743
744 emitStateSensorEventSignal(tid, sensorId, sensorOffset,
745 eventState,
746 previousEventState);
747
748 SensorEntry sensorEntry{tid, sensorId};
749
750 pldm::pdr::EntityInfo entityInfo{};
751 pldm::pdr::CompositeSensorStates
752 compositeSensorStates{};
753
754 try
755 {
756 std::tie(entityInfo, compositeSensorStates) =
757 lookupSensorInfo(sensorEntry);
758 }
759 catch (const std::out_of_range& e)
760 {
761 try
762 {
763 sensorEntry.terminusID = PLDM_TID_RESERVED;
764 std::tie(entityInfo, compositeSensorStates) =
765 lookupSensorInfo(sensorEntry);
766 }
767 catch (const std::out_of_range& e)
768 {
769 std::cerr << "No mapping for the events"
770 << std::endl;
771 }
772 }
773
774 if (sensorOffset > compositeSensorStates.size())
775 {
776 std::cerr
777 << " Error Invalid data, Invalid sensor offset"
778 << std::endl;
779 return;
780 }
781
782 const auto& possibleStates =
783 compositeSensorStates[sensorOffset];
784 if (possibleStates.find(eventState) ==
785 possibleStates.end())
786 {
787 std::cerr
788 << " Error invalid_data, Invalid event state"
789 << std::endl;
790 return;
791 }
792 const auto& [containerId, entityType, entityInstance] =
793 entityInfo;
794 pldm::responder::events::StateSensorEntry
795 stateSensorEntry{containerId, entityType,
796 entityInstance, sensorOffset};
797 handleStateSensorEvent(stateSensorEntry, eventState);
798 }
799 };
800
801 rc = handler->registerRequest(
802 mctp_eid, instanceId, PLDM_PLATFORM,
803 PLDM_GET_STATE_SENSOR_READINGS, std::move(requestMsg),
804 std::move(getStateSensorReadingRespHandler));
805
806 if (rc != PLDM_SUCCESS)
807 {
808 std::cerr << " Failed to send request to get State sensor "
809 "reading on Host "
810 << std::endl;
811 }
812 }
813 }
814 }
815}
Pavithra Barithaya51efaf82020-04-02 02:42:27 -0500816} // namespace pldm