blob: d5df1888be32c7884b83bf1d72ff4bd9919c8b9a [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
George Liu6492f522020-06-16 10:34:05 +08005#include "libpldm/requester/pldm.h"
6
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{
19
Brad Bishop5079ac42021-08-19 18:35:06 -040020using namespace pldm::dbus_api;
21using namespace pldm::responder::events;
Deepak Kodihalli6b1d1ca2020-04-27 07:24:51 -050022using namespace pldm::utils;
23using namespace sdbusplus::bus::match::rules;
Deepak Kodihalli87514cc2020-04-16 09:08:38 -050024using Json = nlohmann::json;
25namespace fs = std::filesystem;
26constexpr auto fruJson = "host_frus.json";
27const Json emptyJson{};
28const std::vector<Json> emptyJsonList{};
29
Tom Joseph74f27c72021-05-16 07:58:53 -070030HostPDRHandler::HostPDRHandler(
31 int mctp_fd, uint8_t mctp_eid, sdeventplus::Event& event, pldm_pdr* repo,
32 const std::string& eventsJsonsDir, pldm_entity_association_tree* entityTree,
33 pldm_entity_association_tree* bmcEntityTree, Requester& requester,
Sampa Misrac0c79482021-06-02 08:01:54 -050034 pldm::requester::Handler<pldm::requester::Request>* handler, bool verbose) :
Deepak Kodihalli87514cc2020-04-16 09:08:38 -050035 mctp_fd(mctp_fd),
Pavithra Barithaya3aec9972020-12-14 01:55:44 -060036 mctp_eid(mctp_eid), event(event), repo(repo),
37 stateSensorHandler(eventsJsonsDir), entityTree(entityTree),
Tom Joseph74f27c72021-05-16 07:58:53 -070038 bmcEntityTree(bmcEntityTree), requester(requester), handler(handler),
39 verbose(verbose)
Deepak Kodihalli87514cc2020-04-16 09:08:38 -050040{
41 fs::path hostFruJson(fs::path(HOST_JSONS_DIR) / fruJson);
42 if (fs::exists(hostFruJson))
43 {
Pavithra Barithayae8beb892020-04-14 23:24:25 -050044 // Note parent entities for entities sent down by the host firmware.
45 // This will enable a merge of entity associations.
Deepak Kodihalli87514cc2020-04-16 09:08:38 -050046 try
47 {
48 std::ifstream jsonFile(hostFruJson);
49 auto data = Json::parse(jsonFile, nullptr, false);
50 if (data.is_discarded())
51 {
52 std::cerr << "Parsing Host FRU json file failed" << std::endl;
53 }
54 else
55 {
56 auto entities = data.value("entities", emptyJsonList);
57 for (auto& entity : entities)
58 {
59 EntityType entityType = entity.value("entity_type", 0);
60 auto parent = entity.value("parent", emptyJson);
61 pldm_entity p{};
62 p.entity_type = parent.value("entity_type", 0);
63 p.entity_instance_num = parent.value("entity_instance", 0);
64 parents.emplace(entityType, std::move(p));
65 }
66 }
67 }
68 catch (const std::exception& e)
69 {
70 std::cerr << "Parsing Host FRU json file failed, exception = "
71 << e.what() << std::endl;
72 }
73 }
Deepak Kodihalli6b1d1ca2020-04-27 07:24:51 -050074
75 hostOffMatch = std::make_unique<sdbusplus::bus::match::match>(
76 pldm::utils::DBusHandler::getBus(),
77 propertiesChanged("/xyz/openbmc_project/state/host0",
78 "xyz.openbmc_project.State.Host"),
Sampa Misrac073a202021-05-08 10:56:05 -050079 [this, repo, entityTree,
80 bmcEntityTree](sdbusplus::message::message& msg) {
Deepak Kodihalli6b1d1ca2020-04-27 07:24:51 -050081 DbusChangedProps props{};
82 std::string intf;
83 msg.read(intf, props);
84 const auto itr = props.find("CurrentHostState");
85 if (itr != props.end())
86 {
87 PropertyValue value = itr->second;
88 auto propVal = std::get<std::string>(value);
89 if (propVal == "xyz.openbmc_project.State.Host.HostState.Off")
90 {
91 pldm_pdr_remove_remote_pdrs(repo);
Sampa Misrac073a202021-05-08 10:56:05 -050092 pldm_entity_association_tree_destroy_root(entityTree);
93 pldm_entity_association_tree_copy_root(bmcEntityTree,
94 entityTree);
Tom Josephb4268602020-04-17 17:20:45 +053095 this->sensorMap.clear();
Deepak Kodihalli6b1d1ca2020-04-27 07:24:51 -050096 }
97 }
98 });
Deepak Kodihalli87514cc2020-04-16 09:08:38 -050099}
100
Deepak Kodihalli7246e0c2020-07-08 06:40:18 -0500101void HostPDRHandler::fetchPDR(PDRRecordHandles&& recordHandles)
Pavithra Barithaya51efaf82020-04-02 02:42:27 -0500102{
Deepak Kodihalli8cb6f662020-04-10 02:55:43 -0500103 pdrRecordHandles.clear();
104 pdrRecordHandles = std::move(recordHandles);
105
106 // Defer the actual fetch of PDRs from the host (by queuing the call on the
107 // main event loop). That way, we can respond to the platform event msg from
108 // the host firmware.
109 pdrFetchEvent = std::make_unique<sdeventplus::source::Defer>(
110 event, std::bind(std::mem_fn(&HostPDRHandler::_fetchPDR), this,
111 std::placeholders::_1));
112}
113
114void HostPDRHandler::_fetchPDR(sdeventplus::source::EventBase& /*source*/)
115{
Sampa Misrac0c79482021-06-02 08:01:54 -0500116 getHostPDR();
117}
118
119void HostPDRHandler::getHostPDR(uint32_t nextRecordHandle)
120{
Deepak Kodihalli8cb6f662020-04-10 02:55:43 -0500121 pdrFetchEvent.reset();
122
Pavithra Barithaya51efaf82020-04-02 02:42:27 -0500123 std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) +
124 PLDM_GET_PDR_REQ_BYTES);
125 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
Deepak Kodihalli7246e0c2020-07-08 06:40:18 -0500126 uint32_t recordHandle{};
Sampa Misrac0c79482021-06-02 08:01:54 -0500127 if (!nextRecordHandle)
Deepak Kodihalli7246e0c2020-07-08 06:40:18 -0500128 {
Sampa Misrac0c79482021-06-02 08:01:54 -0500129 if (!pdrRecordHandles.empty())
130 {
131 recordHandle = pdrRecordHandles.front();
132 pdrRecordHandles.pop_front();
133 }
134 }
135 else
136 {
137 recordHandle = nextRecordHandle;
138 }
139 auto instanceId = requester.getInstanceId(mctp_eid);
140
141 auto rc =
142 encode_get_pdr_req(instanceId, recordHandle, 0, PLDM_GET_FIRSTPART,
143 UINT16_MAX, 0, request, PLDM_GET_PDR_REQ_BYTES);
144 if (rc != PLDM_SUCCESS)
145 {
146 requester.markFree(mctp_eid, instanceId);
147 std::cerr << "Failed to encode_get_pdr_req, rc = " << rc << std::endl;
148 return;
149 }
150 if (verbose)
151 {
152 std::cout << "Sending Msg:" << std::endl;
153 printBuffer(requestMsg, verbose);
Deepak Kodihalli7246e0c2020-07-08 06:40:18 -0500154 }
155
Sampa Misrac0c79482021-06-02 08:01:54 -0500156 rc = handler->registerRequest(
157 mctp_eid, instanceId, PLDM_PLATFORM, PLDM_GET_PDR,
158 std::move(requestMsg),
159 std::move(std::bind_front(&HostPDRHandler::processHostPDRs, this)));
160 if (rc)
Pavithra Barithaya51efaf82020-04-02 02:42:27 -0500161 {
Sampa Misrac0c79482021-06-02 08:01:54 -0500162 std::cerr << "Failed to send the GetPDR request to Host \n";
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500163 }
Pavithra Barithaya51efaf82020-04-02 02:42:27 -0500164}
165
Pavithra Barithaya3aec9972020-12-14 01:55:44 -0600166int HostPDRHandler::handleStateSensorEvent(const StateSensorEntry& entry,
167 pdr::EventState state)
168{
169 auto rc = stateSensorHandler.eventAction(entry, state);
170 if (rc != PLDM_SUCCESS)
171 {
172 std::cerr << "Failed to fetch and update D-bus property, rc = " << rc
173 << std::endl;
174 return rc;
175 }
176 return PLDM_SUCCESS;
177}
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500178bool HostPDRHandler::getParent(EntityType type, pldm_entity& parent)
179{
180 auto found = parents.find(type);
181 if (found != parents.end())
182 {
183 parent.entity_type = found->second.entity_type;
184 parent.entity_instance_num = found->second.entity_instance_num;
185 return true;
186 }
187
188 return false;
189}
190
191void HostPDRHandler::mergeEntityAssociations(const std::vector<uint8_t>& pdr)
192{
193 size_t numEntities{};
194 pldm_entity* entities = nullptr;
195 bool merged = false;
196 auto entityPdr = reinterpret_cast<pldm_pdr_entity_association*>(
197 const_cast<uint8_t*>(pdr.data()) + sizeof(pldm_pdr_hdr));
198
199 pldm_entity_association_pdr_extract(pdr.data(), pdr.size(), &numEntities,
200 &entities);
201 for (size_t i = 0; i < numEntities; ++i)
202 {
203 pldm_entity parent{};
204 if (getParent(entities[i].entity_type, parent))
205 {
206 auto node = pldm_entity_association_tree_find(entityTree, &parent);
207 if (node)
208 {
George Liu64a8f0f2021-06-12 10:56:11 +0800209 pldm_entity_association_tree_add(entityTree, &entities[i],
210 0xFFFF, node,
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500211 entityPdr->association_type);
212 merged = true;
213 }
214 }
215 }
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500216
217 if (merged)
218 {
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500219 // Update our PDR repo with the merged entity association PDRs
Sampa Misra719ed392021-06-04 05:15:13 -0500220 pldm_entity_node* node = nullptr;
221 pldm_find_entity_ref_in_tree(entityTree, entities[0], &node);
222 if (node == nullptr)
223 {
224 std::cerr
225 << "\ncould not find referrence of the entity in the tree \n";
226 }
227 else
228 {
229 pldm_entity_association_pdr_add_from_node(node, repo, &entities,
230 numEntities, true);
231 }
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500232 }
Sampa Misra719ed392021-06-04 05:15:13 -0500233 free(entities);
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500234}
235
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500236void HostPDRHandler::sendPDRRepositoryChgEvent(std::vector<uint8_t>&& pdrTypes,
237 uint8_t eventDataFormat)
238{
239 assert(eventDataFormat == FORMAT_IS_PDR_HANDLES);
240
241 // Extract from the PDR repo record handles of PDRs we want the host
242 // to pull up.
243 std::vector<uint8_t> eventDataOps{PLDM_RECORDS_ADDED};
244 std::vector<uint8_t> numsOfChangeEntries(1);
245 std::vector<std::vector<ChangeEntry>> changeEntries(
246 numsOfChangeEntries.size());
247 for (auto pdrType : pdrTypes)
248 {
249 const pldm_pdr_record* record{};
250 do
251 {
252 record = pldm_pdr_find_record_by_type(repo, pdrType, record,
253 nullptr, nullptr);
254 if (record && pldm_pdr_record_is_remote(record))
255 {
256 changeEntries[0].push_back(
257 pldm_pdr_get_record_handle(repo, record));
258 }
259 } while (record);
260 }
261 if (changeEntries.empty())
262 {
263 return;
264 }
265 numsOfChangeEntries[0] = changeEntries[0].size();
266
267 // Encode PLDM platform event msg to indicate a PDR repo change.
268 size_t maxSize = PLDM_PDR_REPOSITORY_CHG_EVENT_MIN_LENGTH +
269 PLDM_PDR_REPOSITORY_CHANGE_RECORD_MIN_LENGTH +
270 changeEntries[0].size() * sizeof(uint32_t);
271 std::vector<uint8_t> eventDataVec{};
272 eventDataVec.resize(maxSize);
273 auto eventData =
274 reinterpret_cast<struct pldm_pdr_repository_chg_event_data*>(
275 eventDataVec.data());
276 size_t actualSize{};
277 auto firstEntry = changeEntries[0].data();
278 auto rc = encode_pldm_pdr_repository_chg_event_data(
279 eventDataFormat, 1, eventDataOps.data(), numsOfChangeEntries.data(),
280 &firstEntry, eventData, &actualSize, maxSize);
281 if (rc != PLDM_SUCCESS)
282 {
283 std::cerr
284 << "Failed to encode_pldm_pdr_repository_chg_event_data, rc = "
285 << rc << std::endl;
286 return;
287 }
288 auto instanceId = requester.getInstanceId(mctp_eid);
289 std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) +
290 PLDM_PLATFORM_EVENT_MESSAGE_MIN_REQ_BYTES +
291 actualSize);
292 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
293 rc = encode_platform_event_message_req(
294 instanceId, 1, 0, PLDM_PDR_REPOSITORY_CHG_EVENT, eventDataVec.data(),
Christian Geddes3bdb3c22020-05-01 14:55:39 -0500295 actualSize, request,
296 actualSize + PLDM_PLATFORM_EVENT_MESSAGE_MIN_REQ_BYTES);
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500297 if (rc != PLDM_SUCCESS)
298 {
299 requester.markFree(mctp_eid, instanceId);
300 std::cerr << "Failed to encode_platform_event_message_req, rc = " << rc
301 << std::endl;
302 return;
303 }
304
Tom Joseph74f27c72021-05-16 07:58:53 -0700305 auto platformEventMessageResponseHandler = [](mctp_eid_t /*eid*/,
306 const pldm_msg* response,
307 size_t respMsgLen) {
308 if (response == nullptr || !respMsgLen)
309 {
310 std::cerr << "Failed to receive response for the PDR repository "
311 "changed event"
312 << "\n";
313 return;
314 }
315
316 uint8_t completionCode{};
317 uint8_t status{};
318 auto responsePtr = reinterpret_cast<const struct pldm_msg*>(response);
319 auto rc = decode_platform_event_message_resp(
320 responsePtr, respMsgLen - sizeof(pldm_msg_hdr), &completionCode,
321 &status);
Sampa Misrac0c79482021-06-02 08:01:54 -0500322 if (rc || completionCode)
Tom Joseph74f27c72021-05-16 07:58:53 -0700323 {
324 std::cerr << "Failed to decode_platform_event_message_resp: "
325 << "rc=" << rc
326 << ", cc=" << static_cast<unsigned>(completionCode)
327 << std::endl;
328 }
329 };
330
Sampa Misrac0c79482021-06-02 08:01:54 -0500331 rc = handler->registerRequest(
Sampa Misra626c5652021-08-11 10:28:48 -0500332 mctp_eid, instanceId, PLDM_PLATFORM, PLDM_PLATFORM_EVENT_MESSAGE,
Tom Joseph74f27c72021-05-16 07:58:53 -0700333 std::move(requestMsg), std::move(platformEventMessageResponseHandler));
Sampa Misrac0c79482021-06-02 08:01:54 -0500334 if (rc)
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500335 {
Tom Joseph74f27c72021-05-16 07:58:53 -0700336 std::cerr << "Failed to send the PDR repository changed event request"
337 << "\n";
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500338 }
339}
340
Sampa Misra868c8792020-05-26 03:12:13 -0500341void HostPDRHandler::parseStateSensorPDRs(const PDRList& stateSensorPDRs,
342 const TLPDRMap& tlpdrInfo)
343{
344 for (const auto& pdr : stateSensorPDRs)
345 {
346 SensorEntry sensorEntry{};
347 const auto& [terminusHandle, sensorID, sensorInfo] =
348 responder::pdr_utils::parseStateSensorPDR(pdr);
349 sensorEntry.sensorID = sensorID;
350 try
351 {
352 sensorEntry.terminusID = tlpdrInfo.at(terminusHandle);
353 }
354 // If there is no mapping for terminusHandle assign the reserved TID
355 // value of 0xFF to indicate that.
356 catch (const std::out_of_range& e)
357 {
358 sensorEntry.terminusID = PLDM_TID_RESERVED;
359 }
360 sensorMap.emplace(sensorEntry, std::move(sensorInfo));
361 }
362}
363
Sampa Misrac0c79482021-06-02 08:01:54 -0500364void HostPDRHandler::processHostPDRs(mctp_eid_t /*eid*/,
365 const pldm_msg* response,
366 size_t respMsgLen)
367{
368 static bool merged = false;
369 static PDRList stateSensorPDRs{};
370 static TLPDRMap tlpdrInfo{};
371 uint32_t nextRecordHandle{};
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600372 std::vector<TlInfo> tlInfo;
373 uint8_t tlEid = 0;
374 bool tlValid = true;
375 uint32_t rh = 0;
376 uint16_t terminusHandle = 0;
377 uint8_t tid = 0;
378
Sampa Misrac0c79482021-06-02 08:01:54 -0500379 uint8_t completionCode{};
380 uint32_t nextDataTransferHandle{};
381 uint8_t transferFlag{};
382 uint16_t respCount{};
383 uint8_t transferCRC{};
384 if (response == nullptr || !respMsgLen)
385 {
386 std::cerr << "Failed to receive response for the GetPDR"
387 " command \n";
388 return;
389 }
390
391 auto rc = decode_get_pdr_resp(
392 response, respMsgLen /*- sizeof(pldm_msg_hdr)*/, &completionCode,
393 &nextRecordHandle, &nextDataTransferHandle, &transferFlag, &respCount,
394 nullptr, 0, &transferCRC);
395 std::vector<uint8_t> responsePDRMsg;
396 responsePDRMsg.resize(respMsgLen + sizeof(pldm_msg_hdr));
397 memcpy(responsePDRMsg.data(), response, respMsgLen + sizeof(pldm_msg_hdr));
398 if (verbose)
399 {
400 std::cout << "Receiving Msg:" << std::endl;
401 printBuffer(responsePDRMsg, verbose);
402 }
403 if (rc != PLDM_SUCCESS)
404 {
405 std::cerr << "Failed to decode_get_pdr_resp, rc = " << rc << std::endl;
406 return;
407 }
408 else
409 {
410 std::vector<uint8_t> pdr(respCount, 0);
411 rc = decode_get_pdr_resp(response, respMsgLen, &completionCode,
412 &nextRecordHandle, &nextDataTransferHandle,
413 &transferFlag, &respCount, pdr.data(),
414 respCount, &transferCRC);
415 if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS)
416 {
417 std::cerr << "Failed to decode_get_pdr_resp: "
418 << "rc=" << rc
419 << ", cc=" << static_cast<unsigned>(completionCode)
420 << std::endl;
421 return;
422 }
423 else
424 {
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600425 // when nextRecordHandle is 0, we need the recordHandle of the last
426 // PDR and not 0-1.
427 if (!nextRecordHandle)
428 {
429 rh = nextRecordHandle;
430 }
431 else
432 {
433 rh = nextRecordHandle - 1;
434 }
435
Sampa Misrac0c79482021-06-02 08:01:54 -0500436 auto pdrHdr = reinterpret_cast<pldm_pdr_hdr*>(pdr.data());
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600437 if (!rh)
438 {
439 rh = pdrHdr->record_handle;
440 }
441
Sampa Misrac0c79482021-06-02 08:01:54 -0500442 if (pdrHdr->type == PLDM_PDR_ENTITY_ASSOCIATION)
443 {
444 this->mergeEntityAssociations(pdr);
445 merged = true;
446 }
447 else
448 {
449 if (pdrHdr->type == PLDM_TERMINUS_LOCATOR_PDR)
450 {
451 auto tlpdr =
452 reinterpret_cast<const pldm_terminus_locator_pdr*>(
453 pdr.data());
454 tlpdrInfo.emplace(
455 static_cast<pldm::pdr::TerminusHandle>(
456 tlpdr->terminus_handle),
457 static_cast<pldm::pdr::TerminusID>(tlpdr->tid));
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600458
459 terminusHandle = tlpdr->terminus_handle;
460 tid = tlpdr->tid;
461 auto terminus_locator_type = tlpdr->terminus_locator_type;
462 if (terminus_locator_type ==
463 PLDM_TERMINUS_LOCATOR_TYPE_MCTP_EID)
464 {
465 auto locatorValue = reinterpret_cast<
466 const pldm_terminus_locator_type_mctp_eid*>(
467 tlpdr->terminus_locator_value);
468 tlEid = static_cast<uint8_t>(locatorValue->eid);
469 }
470 if (tlpdr->validity == 0)
471 {
472 tlValid = false;
473 }
474 tlInfo.emplace_back(
475 TlInfo{tlpdr->validity, static_cast<uint8_t>(tlEid),
476 tlpdr->tid, tlpdr->terminus_handle});
Sampa Misrac0c79482021-06-02 08:01:54 -0500477 }
478 else if (pdrHdr->type == PLDM_STATE_SENSOR_PDR)
479 {
480 stateSensorPDRs.emplace_back(pdr);
481 }
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600482
483 // if the TLPDR is invalid update the repo accordingly
484 if (!tlValid)
485 {
486 pldm_pdr_update_TL_pdr(repo, terminusHandle, tid, tlEid,
487 tlValid);
488 }
489 else
490 {
491 pldm_pdr_add(repo, pdr.data(), respCount, rh, true);
492 }
Sampa Misrac0c79482021-06-02 08:01:54 -0500493 }
494 }
495 }
496 if (!nextRecordHandle)
497 {
498 /*received last record*/
499 this->parseStateSensorPDRs(stateSensorPDRs, tlpdrInfo);
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600500 if (isHostUp())
501 {
502 this->setHostSensorState(stateSensorPDRs, tlInfo);
503 }
Sampa Misrac0c79482021-06-02 08:01:54 -0500504 stateSensorPDRs.clear();
505 tlpdrInfo.clear();
506 if (merged)
507 {
508 merged = false;
509 deferredPDRRepoChgEvent =
510 std::make_unique<sdeventplus::source::Defer>(
511 event,
512 std::bind(
513 std::mem_fn((&HostPDRHandler::_processPDRRepoChgEvent)),
514 this, std::placeholders::_1));
515 }
516 }
517 else
518 {
519 deferredFetchPDREvent = std::make_unique<sdeventplus::source::Defer>(
520 event,
521 std::bind(std::mem_fn((&HostPDRHandler::_processFetchPDREvent)),
522 this, nextRecordHandle, std::placeholders::_1));
523 }
524}
525
526void HostPDRHandler::_processPDRRepoChgEvent(
527 sdeventplus::source::EventBase& /*source */)
528{
529 deferredPDRRepoChgEvent.reset();
530 this->sendPDRRepositoryChgEvent(
531 std::move(std::vector<uint8_t>(1, PLDM_PDR_ENTITY_ASSOCIATION)),
532 FORMAT_IS_PDR_HANDLES);
533}
534
535void HostPDRHandler::_processFetchPDREvent(
536 uint32_t nextRecordHandle, sdeventplus::source::EventBase& /*source */)
537{
538 deferredFetchPDREvent.reset();
539 if (!this->pdrRecordHandles.empty())
540 {
541 nextRecordHandle = this->pdrRecordHandles.front();
542 this->pdrRecordHandles.pop_front();
543 }
544 this->getHostPDR(nextRecordHandle);
545}
546
sampmisr6decfc12021-03-02 11:07:36 +0530547void HostPDRHandler::setHostState()
548{
549 using namespace sdeventplus;
550 using namespace sdeventplus::source;
551 constexpr auto clockId = sdeventplus::ClockId::RealTime;
552 using Clock = Clock<clockId>;
553 using Timer = Time<clockId>;
554
555 auto event1 = sdeventplus::Event::get_default();
556 auto& bus = pldm::utils::DBusHandler::getBus();
557 bus.attach_event(event1.get(), SD_EVENT_PRIORITY_NORMAL);
558
559 responseReceived = false;
560 timeOut = false;
561
562 int fd = pldm_open();
563 if (-1 == fd)
564 {
565 std::cerr << "Failed to connect to mctp demux daemon \n";
566 return;
567 }
568
569 auto timerCallback = [=, this](Timer& /*source*/,
570 Timer::TimePoint /*time*/) {
571 timeOut = true;
572 if (!responseReceived)
573 {
574 std::cout << "PLDM did not get a response from Host"
575 " Host seems to be off \n";
576 }
577 return;
578 };
579
580 Timer time(event1, (Clock(event1).now() + std::chrono::seconds{3}),
581 std::chrono::seconds{1}, std::move(timerCallback));
582
583 auto callback = [=, this](IO& /*io*/, int fd, uint32_t revents) {
584 if (!(revents & EPOLLIN))
585 {
586 return;
587 }
588 uint8_t* responseMsg = nullptr;
589 size_t responseMsgSize{};
590 auto rc =
591 pldm_recv(mctp_eid, fd, insId, &responseMsg, &responseMsgSize);
592 if (rc != PLDM_REQUESTER_SUCCESS)
593 {
594 return;
595 }
596 std::unique_ptr<uint8_t, decltype(std::free)*> responseMsgPtr{
597 responseMsg, std::free};
598 auto response = reinterpret_cast<pldm_msg*>(responseMsgPtr.get());
599 std::cout << "Getting the response. PLDM RC = " << std::hex
600 << std::showbase
601 << static_cast<uint16_t>(response->payload[0]) << "\n";
602 responseReceived = true;
603 return;
604 };
605 IO io(event1, fd, EPOLLIN, std::move(callback));
606 std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) +
607 PLDM_GET_PDR_REQ_BYTES);
608 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
609 uint32_t recordHandle{};
610 insId = requester.getInstanceId(mctp_eid);
611 auto rc =
612 encode_get_pdr_req(insId, recordHandle, 0, PLDM_GET_FIRSTPART,
613 UINT16_MAX, 0, request, PLDM_GET_PDR_REQ_BYTES);
614 if (rc != PLDM_SUCCESS)
615 {
616 requester.markFree(mctp_eid, insId);
617 std::cerr << "Failed to encode_get_pdr_req, rc = " << rc << std::endl;
618 return;
619 }
620 rc = pldm_send(mctp_eid, fd, requestMsg.data(), requestMsg.size());
621 if (0 > rc)
622 {
623 std::cerr << "Failed to send message RC = " << rc
624 << ", errno = " << errno << "\n";
625 return;
626 }
627 while (1)
628 {
629 if (responseReceived)
630 {
631 requester.markFree(mctp_eid, insId);
632 break;
633 }
634 if (timeOut)
635 {
636 requester.markFree(mctp_eid, insId);
637 break;
638 }
639 try
640 {
641 event1.run(std::nullopt);
642 }
643 catch (const sdeventplus::SdEventError& e)
644 {
645 std::cerr << "Failure in processing request.ERROR= " << e.what()
646 << "\n";
647 return;
648 }
649 }
650}
651
652bool HostPDRHandler::isHostUp()
653{
654 return responseReceived;
655}
656
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600657void HostPDRHandler::setHostSensorState(const PDRList& stateSensorPDRs,
658 const std::vector<TlInfo>& tlinfo)
659{
660 for (const auto& stateSensorPDR : stateSensorPDRs)
661 {
662 auto pdr = reinterpret_cast<const pldm_state_sensor_pdr*>(
663 stateSensorPDR.data());
664
665 if (!pdr)
666 {
667 std::cerr << "Failed to get State sensor PDR" << std::endl;
668 pldm::utils::reportError(
669 "xyz.openbmc_project.bmc.pldm.InternalFailure");
670 return;
671 }
672
673 uint16_t sensorId = pdr->sensor_id;
674
675 for (auto info : tlinfo)
676 {
677 if (info.terminusHandle == pdr->terminus_handle)
678 {
679 if (info.valid == PLDM_TL_PDR_VALID)
680 {
681 mctp_eid = info.eid;
682 }
683
684 bitfield8_t sensorRearm;
685 sensorRearm.byte = 0;
686 uint8_t tid = info.tid;
687
688 auto instanceId = requester.getInstanceId(mctp_eid);
689 std::vector<uint8_t> requestMsg(
690 sizeof(pldm_msg_hdr) +
691 PLDM_GET_STATE_SENSOR_READINGS_REQ_BYTES);
692 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
693 auto rc = encode_get_state_sensor_readings_req(
694 instanceId, sensorId, sensorRearm, 0, request);
695
696 if (rc != PLDM_SUCCESS)
697 {
698 requester.markFree(mctp_eid, instanceId);
699 std::cerr << "Failed to "
700 "encode_get_state_sensor_readings_req, rc = "
701 << rc << std::endl;
702 pldm::utils::reportError(
703 "xyz.openbmc_project.bmc.pldm.InternalFailure");
704 return;
705 }
706
707 auto getStateSensorReadingRespHandler = [=, this](
708 mctp_eid_t /*eid*/,
709 const pldm_msg*
710 response,
711 size_t respMsgLen) {
712 if (response == nullptr || !respMsgLen)
713 {
714 std::cerr << "Failed to receive response for "
715 "getStateSensorReading command \n";
716 return;
717 }
718 std::array<get_sensor_state_field, 8> stateField{};
719 uint8_t completionCode = 0;
720 uint8_t comp_sensor_count = 0;
721
722 auto rc = decode_get_state_sensor_readings_resp(
723 response, respMsgLen, &completionCode,
724 &comp_sensor_count, stateField.data());
725
726 if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS)
727 {
728 std::cerr
729 << "Failed to "
730 "decode_get_state_sensor_readings_resp, rc = "
731 << rc
732 << " cc=" << static_cast<unsigned>(completionCode)
733 << std::endl;
734 pldm::utils::reportError(
735 "xyz.openbmc_project.bmc.pldm.InternalFailure");
736 }
737
738 uint8_t eventState;
739 uint8_t previousEventState;
740 uint8_t sensorOffset = comp_sensor_count - 1;
741
742 for (size_t i = 0; i < comp_sensor_count; i++)
743 {
744 eventState = stateField[i].present_state;
745 previousEventState = stateField[i].previous_state;
746
747 emitStateSensorEventSignal(tid, sensorId, sensorOffset,
748 eventState,
749 previousEventState);
750
751 SensorEntry sensorEntry{tid, sensorId};
752
753 pldm::pdr::EntityInfo entityInfo{};
754 pldm::pdr::CompositeSensorStates
755 compositeSensorStates{};
756
757 try
758 {
759 std::tie(entityInfo, compositeSensorStates) =
760 lookupSensorInfo(sensorEntry);
761 }
762 catch (const std::out_of_range& e)
763 {
764 try
765 {
766 sensorEntry.terminusID = PLDM_TID_RESERVED;
767 std::tie(entityInfo, compositeSensorStates) =
768 lookupSensorInfo(sensorEntry);
769 }
770 catch (const std::out_of_range& e)
771 {
772 std::cerr << "No mapping for the events"
773 << std::endl;
774 }
775 }
776
777 if (sensorOffset > compositeSensorStates.size())
778 {
779 std::cerr
780 << " Error Invalid data, Invalid sensor offset"
781 << std::endl;
782 return;
783 }
784
785 const auto& possibleStates =
786 compositeSensorStates[sensorOffset];
787 if (possibleStates.find(eventState) ==
788 possibleStates.end())
789 {
790 std::cerr
791 << " Error invalid_data, Invalid event state"
792 << std::endl;
793 return;
794 }
795 const auto& [containerId, entityType, entityInstance] =
796 entityInfo;
797 pldm::responder::events::StateSensorEntry
798 stateSensorEntry{containerId, entityType,
799 entityInstance, sensorOffset};
800 handleStateSensorEvent(stateSensorEntry, eventState);
801 }
802 };
803
804 rc = handler->registerRequest(
805 mctp_eid, instanceId, PLDM_PLATFORM,
806 PLDM_GET_STATE_SENSOR_READINGS, std::move(requestMsg),
807 std::move(getStateSensorReadingRespHandler));
808
809 if (rc != PLDM_SUCCESS)
810 {
811 std::cerr << " Failed to send request to get State sensor "
812 "reading on Host "
813 << std::endl;
814 }
815 }
816 }
817 }
818}
Pavithra Barithaya51efaf82020-04-02 02:42:27 -0500819} // namespace pldm