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