blob: e5a3e6ba5aed426065a2031dbc7d2a90ebf79260 [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,
Tom Josephe5268cd2021-09-07 13:04:03 +053034 pldm::requester::Handler<pldm::requester::Request>* handler) :
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 Josephe5268cd2021-09-07 13:04:03 +053038 bmcEntityTree(bmcEntityTree), requester(requester), handler(handler)
Deepak Kodihalli87514cc2020-04-16 09:08:38 -050039{
40 fs::path hostFruJson(fs::path(HOST_JSONS_DIR) / fruJson);
41 if (fs::exists(hostFruJson))
42 {
Pavithra Barithayae8beb892020-04-14 23:24:25 -050043 // Note parent entities for entities sent down by the host firmware.
44 // This will enable a merge of entity associations.
Deepak Kodihalli87514cc2020-04-16 09:08:38 -050045 try
46 {
47 std::ifstream jsonFile(hostFruJson);
48 auto data = Json::parse(jsonFile, nullptr, false);
49 if (data.is_discarded())
50 {
51 std::cerr << "Parsing Host FRU json file failed" << std::endl;
52 }
53 else
54 {
55 auto entities = data.value("entities", emptyJsonList);
56 for (auto& entity : entities)
57 {
58 EntityType entityType = entity.value("entity_type", 0);
59 auto parent = entity.value("parent", emptyJson);
60 pldm_entity p{};
61 p.entity_type = parent.value("entity_type", 0);
62 p.entity_instance_num = parent.value("entity_instance", 0);
63 parents.emplace(entityType, std::move(p));
64 }
65 }
66 }
67 catch (const std::exception& e)
68 {
69 std::cerr << "Parsing Host FRU json file failed, exception = "
70 << e.what() << std::endl;
71 }
72 }
Deepak Kodihalli6b1d1ca2020-04-27 07:24:51 -050073
74 hostOffMatch = std::make_unique<sdbusplus::bus::match::match>(
75 pldm::utils::DBusHandler::getBus(),
76 propertiesChanged("/xyz/openbmc_project/state/host0",
77 "xyz.openbmc_project.State.Host"),
Sampa Misrac073a202021-05-08 10:56:05 -050078 [this, repo, entityTree,
79 bmcEntityTree](sdbusplus::message::message& msg) {
Deepak Kodihalli6b1d1ca2020-04-27 07:24:51 -050080 DbusChangedProps props{};
81 std::string intf;
82 msg.read(intf, props);
83 const auto itr = props.find("CurrentHostState");
84 if (itr != props.end())
85 {
86 PropertyValue value = itr->second;
87 auto propVal = std::get<std::string>(value);
88 if (propVal == "xyz.openbmc_project.State.Host.HostState.Off")
89 {
90 pldm_pdr_remove_remote_pdrs(repo);
Sampa Misrac073a202021-05-08 10:56:05 -050091 pldm_entity_association_tree_destroy_root(entityTree);
92 pldm_entity_association_tree_copy_root(bmcEntityTree,
93 entityTree);
Tom Josephb4268602020-04-17 17:20:45 +053094 this->sensorMap.clear();
Deepak Kodihalli6b1d1ca2020-04-27 07:24:51 -050095 }
96 }
97 });
Deepak Kodihalli87514cc2020-04-16 09:08:38 -050098}
99
Deepak Kodihalli7246e0c2020-07-08 06:40:18 -0500100void HostPDRHandler::fetchPDR(PDRRecordHandles&& recordHandles)
Pavithra Barithaya51efaf82020-04-02 02:42:27 -0500101{
Deepak Kodihalli8cb6f662020-04-10 02:55:43 -0500102 pdrRecordHandles.clear();
103 pdrRecordHandles = std::move(recordHandles);
104
105 // Defer the actual fetch of PDRs from the host (by queuing the call on the
106 // main event loop). That way, we can respond to the platform event msg from
107 // the host firmware.
108 pdrFetchEvent = std::make_unique<sdeventplus::source::Defer>(
109 event, std::bind(std::mem_fn(&HostPDRHandler::_fetchPDR), this,
110 std::placeholders::_1));
111}
112
113void HostPDRHandler::_fetchPDR(sdeventplus::source::EventBase& /*source*/)
114{
Sampa Misrac0c79482021-06-02 08:01:54 -0500115 getHostPDR();
116}
117
118void HostPDRHandler::getHostPDR(uint32_t nextRecordHandle)
119{
Deepak Kodihalli8cb6f662020-04-10 02:55:43 -0500120 pdrFetchEvent.reset();
121
Pavithra Barithaya51efaf82020-04-02 02:42:27 -0500122 std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) +
123 PLDM_GET_PDR_REQ_BYTES);
124 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
Deepak Kodihalli7246e0c2020-07-08 06:40:18 -0500125 uint32_t recordHandle{};
Sampa Misrac0c79482021-06-02 08:01:54 -0500126 if (!nextRecordHandle)
Deepak Kodihalli7246e0c2020-07-08 06:40:18 -0500127 {
Sampa Misrac0c79482021-06-02 08:01:54 -0500128 if (!pdrRecordHandles.empty())
129 {
130 recordHandle = pdrRecordHandles.front();
131 pdrRecordHandles.pop_front();
132 }
133 }
134 else
135 {
136 recordHandle = nextRecordHandle;
137 }
138 auto instanceId = requester.getInstanceId(mctp_eid);
139
140 auto rc =
141 encode_get_pdr_req(instanceId, recordHandle, 0, PLDM_GET_FIRSTPART,
142 UINT16_MAX, 0, request, PLDM_GET_PDR_REQ_BYTES);
143 if (rc != PLDM_SUCCESS)
144 {
145 requester.markFree(mctp_eid, instanceId);
146 std::cerr << "Failed to encode_get_pdr_req, rc = " << rc << std::endl;
147 return;
148 }
Deepak Kodihalli7246e0c2020-07-08 06:40:18 -0500149
Sampa Misrac0c79482021-06-02 08:01:54 -0500150 rc = handler->registerRequest(
151 mctp_eid, instanceId, PLDM_PLATFORM, PLDM_GET_PDR,
152 std::move(requestMsg),
153 std::move(std::bind_front(&HostPDRHandler::processHostPDRs, this)));
154 if (rc)
Pavithra Barithaya51efaf82020-04-02 02:42:27 -0500155 {
Sampa Misrac0c79482021-06-02 08:01:54 -0500156 std::cerr << "Failed to send the GetPDR request to Host \n";
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500157 }
Pavithra Barithaya51efaf82020-04-02 02:42:27 -0500158}
159
Pavithra Barithaya3aec9972020-12-14 01:55:44 -0600160int HostPDRHandler::handleStateSensorEvent(const StateSensorEntry& entry,
161 pdr::EventState state)
162{
163 auto rc = stateSensorHandler.eventAction(entry, state);
164 if (rc != PLDM_SUCCESS)
165 {
166 std::cerr << "Failed to fetch and update D-bus property, rc = " << rc
167 << std::endl;
168 return rc;
169 }
170 return PLDM_SUCCESS;
171}
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500172bool HostPDRHandler::getParent(EntityType type, pldm_entity& parent)
173{
174 auto found = parents.find(type);
175 if (found != parents.end())
176 {
177 parent.entity_type = found->second.entity_type;
178 parent.entity_instance_num = found->second.entity_instance_num;
179 return true;
180 }
181
182 return false;
183}
184
185void HostPDRHandler::mergeEntityAssociations(const std::vector<uint8_t>& pdr)
186{
187 size_t numEntities{};
188 pldm_entity* entities = nullptr;
189 bool merged = false;
190 auto entityPdr = reinterpret_cast<pldm_pdr_entity_association*>(
191 const_cast<uint8_t*>(pdr.data()) + sizeof(pldm_pdr_hdr));
192
193 pldm_entity_association_pdr_extract(pdr.data(), pdr.size(), &numEntities,
194 &entities);
195 for (size_t i = 0; i < numEntities; ++i)
196 {
197 pldm_entity parent{};
198 if (getParent(entities[i].entity_type, parent))
199 {
200 auto node = pldm_entity_association_tree_find(entityTree, &parent);
201 if (node)
202 {
George Liu64a8f0f2021-06-12 10:56:11 +0800203 pldm_entity_association_tree_add(entityTree, &entities[i],
204 0xFFFF, node,
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500205 entityPdr->association_type);
206 merged = true;
207 }
208 }
209 }
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500210
211 if (merged)
212 {
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500213 // Update our PDR repo with the merged entity association PDRs
Sampa Misra719ed392021-06-04 05:15:13 -0500214 pldm_entity_node* node = nullptr;
215 pldm_find_entity_ref_in_tree(entityTree, entities[0], &node);
216 if (node == nullptr)
217 {
218 std::cerr
219 << "\ncould not find referrence of the entity in the tree \n";
220 }
221 else
222 {
223 pldm_entity_association_pdr_add_from_node(node, repo, &entities,
224 numEntities, true);
225 }
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500226 }
Sampa Misra719ed392021-06-04 05:15:13 -0500227 free(entities);
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500228}
229
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500230void HostPDRHandler::sendPDRRepositoryChgEvent(std::vector<uint8_t>&& pdrTypes,
231 uint8_t eventDataFormat)
232{
233 assert(eventDataFormat == FORMAT_IS_PDR_HANDLES);
234
235 // Extract from the PDR repo record handles of PDRs we want the host
236 // to pull up.
237 std::vector<uint8_t> eventDataOps{PLDM_RECORDS_ADDED};
238 std::vector<uint8_t> numsOfChangeEntries(1);
239 std::vector<std::vector<ChangeEntry>> changeEntries(
240 numsOfChangeEntries.size());
241 for (auto pdrType : pdrTypes)
242 {
243 const pldm_pdr_record* record{};
244 do
245 {
246 record = pldm_pdr_find_record_by_type(repo, pdrType, record,
247 nullptr, nullptr);
248 if (record && pldm_pdr_record_is_remote(record))
249 {
250 changeEntries[0].push_back(
251 pldm_pdr_get_record_handle(repo, record));
252 }
253 } while (record);
254 }
255 if (changeEntries.empty())
256 {
257 return;
258 }
259 numsOfChangeEntries[0] = changeEntries[0].size();
260
261 // Encode PLDM platform event msg to indicate a PDR repo change.
262 size_t maxSize = PLDM_PDR_REPOSITORY_CHG_EVENT_MIN_LENGTH +
263 PLDM_PDR_REPOSITORY_CHANGE_RECORD_MIN_LENGTH +
264 changeEntries[0].size() * sizeof(uint32_t);
265 std::vector<uint8_t> eventDataVec{};
266 eventDataVec.resize(maxSize);
267 auto eventData =
268 reinterpret_cast<struct pldm_pdr_repository_chg_event_data*>(
269 eventDataVec.data());
270 size_t actualSize{};
271 auto firstEntry = changeEntries[0].data();
272 auto rc = encode_pldm_pdr_repository_chg_event_data(
273 eventDataFormat, 1, eventDataOps.data(), numsOfChangeEntries.data(),
274 &firstEntry, eventData, &actualSize, maxSize);
275 if (rc != PLDM_SUCCESS)
276 {
277 std::cerr
278 << "Failed to encode_pldm_pdr_repository_chg_event_data, rc = "
279 << rc << std::endl;
280 return;
281 }
282 auto instanceId = requester.getInstanceId(mctp_eid);
283 std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) +
284 PLDM_PLATFORM_EVENT_MESSAGE_MIN_REQ_BYTES +
285 actualSize);
286 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
287 rc = encode_platform_event_message_req(
288 instanceId, 1, 0, PLDM_PDR_REPOSITORY_CHG_EVENT, eventDataVec.data(),
Christian Geddes3bdb3c22020-05-01 14:55:39 -0500289 actualSize, request,
290 actualSize + PLDM_PLATFORM_EVENT_MESSAGE_MIN_REQ_BYTES);
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500291 if (rc != PLDM_SUCCESS)
292 {
293 requester.markFree(mctp_eid, instanceId);
294 std::cerr << "Failed to encode_platform_event_message_req, rc = " << rc
295 << std::endl;
296 return;
297 }
298
Tom Joseph74f27c72021-05-16 07:58:53 -0700299 auto platformEventMessageResponseHandler = [](mctp_eid_t /*eid*/,
300 const pldm_msg* response,
301 size_t respMsgLen) {
302 if (response == nullptr || !respMsgLen)
303 {
304 std::cerr << "Failed to receive response for the PDR repository "
305 "changed event"
306 << "\n";
307 return;
308 }
309
310 uint8_t completionCode{};
311 uint8_t status{};
312 auto responsePtr = reinterpret_cast<const struct pldm_msg*>(response);
Pavithra Barithaya54b5a562021-09-27 06:07:10 -0500313 auto rc = decode_platform_event_message_resp(responsePtr, respMsgLen,
314 &completionCode, &status);
Sampa Misrac0c79482021-06-02 08:01:54 -0500315 if (rc || completionCode)
Tom Joseph74f27c72021-05-16 07:58:53 -0700316 {
317 std::cerr << "Failed to decode_platform_event_message_resp: "
318 << "rc=" << rc
319 << ", cc=" << static_cast<unsigned>(completionCode)
320 << std::endl;
321 }
322 };
323
Sampa Misrac0c79482021-06-02 08:01:54 -0500324 rc = handler->registerRequest(
Sampa Misra626c5652021-08-11 10:28:48 -0500325 mctp_eid, instanceId, PLDM_PLATFORM, PLDM_PLATFORM_EVENT_MESSAGE,
Tom Joseph74f27c72021-05-16 07:58:53 -0700326 std::move(requestMsg), std::move(platformEventMessageResponseHandler));
Sampa Misrac0c79482021-06-02 08:01:54 -0500327 if (rc)
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500328 {
Tom Joseph74f27c72021-05-16 07:58:53 -0700329 std::cerr << "Failed to send the PDR repository changed event request"
330 << "\n";
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500331 }
332}
333
Sampa Misra868c8792020-05-26 03:12:13 -0500334void HostPDRHandler::parseStateSensorPDRs(const PDRList& stateSensorPDRs,
335 const TLPDRMap& tlpdrInfo)
336{
337 for (const auto& pdr : stateSensorPDRs)
338 {
339 SensorEntry sensorEntry{};
340 const auto& [terminusHandle, sensorID, sensorInfo] =
341 responder::pdr_utils::parseStateSensorPDR(pdr);
342 sensorEntry.sensorID = sensorID;
343 try
344 {
345 sensorEntry.terminusID = tlpdrInfo.at(terminusHandle);
346 }
347 // If there is no mapping for terminusHandle assign the reserved TID
348 // value of 0xFF to indicate that.
349 catch (const std::out_of_range& e)
350 {
351 sensorEntry.terminusID = PLDM_TID_RESERVED;
352 }
353 sensorMap.emplace(sensorEntry, std::move(sensorInfo));
354 }
355}
356
Sampa Misrac0c79482021-06-02 08:01:54 -0500357void HostPDRHandler::processHostPDRs(mctp_eid_t /*eid*/,
358 const pldm_msg* response,
359 size_t respMsgLen)
360{
361 static bool merged = false;
362 static PDRList stateSensorPDRs{};
363 static TLPDRMap tlpdrInfo{};
364 uint32_t nextRecordHandle{};
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600365 std::vector<TlInfo> tlInfo;
366 uint8_t tlEid = 0;
367 bool tlValid = true;
368 uint32_t rh = 0;
369 uint16_t terminusHandle = 0;
370 uint8_t tid = 0;
371
Sampa Misrac0c79482021-06-02 08:01:54 -0500372 uint8_t completionCode{};
373 uint32_t nextDataTransferHandle{};
374 uint8_t transferFlag{};
375 uint16_t respCount{};
376 uint8_t transferCRC{};
377 if (response == nullptr || !respMsgLen)
378 {
379 std::cerr << "Failed to receive response for the GetPDR"
380 " command \n";
381 return;
382 }
383
384 auto rc = decode_get_pdr_resp(
385 response, respMsgLen /*- sizeof(pldm_msg_hdr)*/, &completionCode,
386 &nextRecordHandle, &nextDataTransferHandle, &transferFlag, &respCount,
387 nullptr, 0, &transferCRC);
388 std::vector<uint8_t> responsePDRMsg;
389 responsePDRMsg.resize(respMsgLen + sizeof(pldm_msg_hdr));
390 memcpy(responsePDRMsg.data(), response, respMsgLen + sizeof(pldm_msg_hdr));
Sampa Misrac0c79482021-06-02 08:01:54 -0500391 if (rc != PLDM_SUCCESS)
392 {
393 std::cerr << "Failed to decode_get_pdr_resp, rc = " << rc << std::endl;
394 return;
395 }
396 else
397 {
398 std::vector<uint8_t> pdr(respCount, 0);
399 rc = decode_get_pdr_resp(response, respMsgLen, &completionCode,
400 &nextRecordHandle, &nextDataTransferHandle,
401 &transferFlag, &respCount, pdr.data(),
402 respCount, &transferCRC);
403 if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS)
404 {
405 std::cerr << "Failed to decode_get_pdr_resp: "
406 << "rc=" << rc
407 << ", cc=" << static_cast<unsigned>(completionCode)
408 << std::endl;
409 return;
410 }
411 else
412 {
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600413 // when nextRecordHandle is 0, we need the recordHandle of the last
414 // PDR and not 0-1.
415 if (!nextRecordHandle)
416 {
417 rh = nextRecordHandle;
418 }
419 else
420 {
421 rh = nextRecordHandle - 1;
422 }
423
Sampa Misrac0c79482021-06-02 08:01:54 -0500424 auto pdrHdr = reinterpret_cast<pldm_pdr_hdr*>(pdr.data());
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600425 if (!rh)
426 {
427 rh = pdrHdr->record_handle;
428 }
429
Sampa Misrac0c79482021-06-02 08:01:54 -0500430 if (pdrHdr->type == PLDM_PDR_ENTITY_ASSOCIATION)
431 {
432 this->mergeEntityAssociations(pdr);
433 merged = true;
434 }
435 else
436 {
437 if (pdrHdr->type == PLDM_TERMINUS_LOCATOR_PDR)
438 {
439 auto tlpdr =
440 reinterpret_cast<const pldm_terminus_locator_pdr*>(
441 pdr.data());
442 tlpdrInfo.emplace(
443 static_cast<pldm::pdr::TerminusHandle>(
444 tlpdr->terminus_handle),
445 static_cast<pldm::pdr::TerminusID>(tlpdr->tid));
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600446
447 terminusHandle = tlpdr->terminus_handle;
448 tid = tlpdr->tid;
449 auto terminus_locator_type = tlpdr->terminus_locator_type;
450 if (terminus_locator_type ==
451 PLDM_TERMINUS_LOCATOR_TYPE_MCTP_EID)
452 {
453 auto locatorValue = reinterpret_cast<
454 const pldm_terminus_locator_type_mctp_eid*>(
455 tlpdr->terminus_locator_value);
456 tlEid = static_cast<uint8_t>(locatorValue->eid);
457 }
458 if (tlpdr->validity == 0)
459 {
460 tlValid = false;
461 }
462 tlInfo.emplace_back(
463 TlInfo{tlpdr->validity, static_cast<uint8_t>(tlEid),
464 tlpdr->tid, tlpdr->terminus_handle});
Sampa Misrac0c79482021-06-02 08:01:54 -0500465 }
466 else if (pdrHdr->type == PLDM_STATE_SENSOR_PDR)
467 {
468 stateSensorPDRs.emplace_back(pdr);
469 }
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600470
471 // if the TLPDR is invalid update the repo accordingly
472 if (!tlValid)
473 {
474 pldm_pdr_update_TL_pdr(repo, terminusHandle, tid, tlEid,
475 tlValid);
476 }
477 else
478 {
479 pldm_pdr_add(repo, pdr.data(), respCount, rh, true);
480 }
Sampa Misrac0c79482021-06-02 08:01:54 -0500481 }
482 }
483 }
484 if (!nextRecordHandle)
485 {
486 /*received last record*/
487 this->parseStateSensorPDRs(stateSensorPDRs, tlpdrInfo);
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600488 if (isHostUp())
489 {
490 this->setHostSensorState(stateSensorPDRs, tlInfo);
491 }
Sampa Misrac0c79482021-06-02 08:01:54 -0500492 stateSensorPDRs.clear();
493 tlpdrInfo.clear();
494 if (merged)
495 {
496 merged = false;
497 deferredPDRRepoChgEvent =
498 std::make_unique<sdeventplus::source::Defer>(
499 event,
500 std::bind(
501 std::mem_fn((&HostPDRHandler::_processPDRRepoChgEvent)),
502 this, std::placeholders::_1));
503 }
504 }
505 else
506 {
507 deferredFetchPDREvent = std::make_unique<sdeventplus::source::Defer>(
508 event,
509 std::bind(std::mem_fn((&HostPDRHandler::_processFetchPDREvent)),
510 this, nextRecordHandle, std::placeholders::_1));
511 }
512}
513
514void HostPDRHandler::_processPDRRepoChgEvent(
515 sdeventplus::source::EventBase& /*source */)
516{
517 deferredPDRRepoChgEvent.reset();
518 this->sendPDRRepositoryChgEvent(
519 std::move(std::vector<uint8_t>(1, PLDM_PDR_ENTITY_ASSOCIATION)),
520 FORMAT_IS_PDR_HANDLES);
521}
522
523void HostPDRHandler::_processFetchPDREvent(
524 uint32_t nextRecordHandle, sdeventplus::source::EventBase& /*source */)
525{
526 deferredFetchPDREvent.reset();
527 if (!this->pdrRecordHandles.empty())
528 {
529 nextRecordHandle = this->pdrRecordHandles.front();
530 this->pdrRecordHandles.pop_front();
531 }
532 this->getHostPDR(nextRecordHandle);
533}
534
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500535void HostPDRHandler::setHostFirmwareCondition()
sampmisr6decfc12021-03-02 11:07:36 +0530536{
sampmisr6decfc12021-03-02 11:07:36 +0530537 responseReceived = false;
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500538 auto instanceId = requester.getInstanceId(mctp_eid);
539 std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) +
540 PLDM_GET_VERSION_REQ_BYTES);
541 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
542 auto rc = encode_get_version_req(instanceId, 0, PLDM_GET_FIRSTPART,
543 PLDM_BASE, request);
544 if (rc != PLDM_SUCCESS)
sampmisr6decfc12021-03-02 11:07:36 +0530545 {
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500546 std::cerr << "GetPLDMVersion encode failure. PLDM error code = "
547 << std::hex << std::showbase << rc << "\n";
548 requester.markFree(mctp_eid, instanceId);
sampmisr6decfc12021-03-02 11:07:36 +0530549 return;
550 }
551
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500552 auto getPLDMVersionHandler = [this](mctp_eid_t /*eid*/,
553 const pldm_msg* response,
554 size_t respMsgLen) {
555 if (response == nullptr || !respMsgLen)
sampmisr6decfc12021-03-02 11:07:36 +0530556 {
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500557 std::cerr << "Failed to receive response for "
558 << "getPLDMVersion command, Host seems to be off \n";
sampmisr6decfc12021-03-02 11:07:36 +0530559 return;
560 }
sampmisr6decfc12021-03-02 11:07:36 +0530561 std::cout << "Getting the response. PLDM RC = " << std::hex
562 << std::showbase
563 << static_cast<uint16_t>(response->payload[0]) << "\n";
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500564 this->responseReceived = true;
565 getHostPDR();
sampmisr6decfc12021-03-02 11:07:36 +0530566 };
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500567 rc = handler->registerRequest(mctp_eid, instanceId, PLDM_BASE,
568 PLDM_GET_PLDM_VERSION, std::move(requestMsg),
569 std::move(getPLDMVersionHandler));
570 if (rc)
sampmisr6decfc12021-03-02 11:07:36 +0530571 {
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500572 std::cerr << "Failed to discover Host state. Assuming Host as off \n";
sampmisr6decfc12021-03-02 11:07:36 +0530573 }
574}
575
576bool HostPDRHandler::isHostUp()
577{
578 return responseReceived;
579}
580
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600581void HostPDRHandler::setHostSensorState(const PDRList& stateSensorPDRs,
582 const std::vector<TlInfo>& tlinfo)
583{
584 for (const auto& stateSensorPDR : stateSensorPDRs)
585 {
586 auto pdr = reinterpret_cast<const pldm_state_sensor_pdr*>(
587 stateSensorPDR.data());
588
589 if (!pdr)
590 {
591 std::cerr << "Failed to get State sensor PDR" << std::endl;
592 pldm::utils::reportError(
593 "xyz.openbmc_project.bmc.pldm.InternalFailure");
594 return;
595 }
596
597 uint16_t sensorId = pdr->sensor_id;
598
599 for (auto info : tlinfo)
600 {
601 if (info.terminusHandle == pdr->terminus_handle)
602 {
603 if (info.valid == PLDM_TL_PDR_VALID)
604 {
605 mctp_eid = info.eid;
606 }
607
608 bitfield8_t sensorRearm;
609 sensorRearm.byte = 0;
610 uint8_t tid = info.tid;
611
612 auto instanceId = requester.getInstanceId(mctp_eid);
613 std::vector<uint8_t> requestMsg(
614 sizeof(pldm_msg_hdr) +
615 PLDM_GET_STATE_SENSOR_READINGS_REQ_BYTES);
616 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
617 auto rc = encode_get_state_sensor_readings_req(
618 instanceId, sensorId, sensorRearm, 0, request);
619
620 if (rc != PLDM_SUCCESS)
621 {
622 requester.markFree(mctp_eid, instanceId);
623 std::cerr << "Failed to "
624 "encode_get_state_sensor_readings_req, rc = "
625 << rc << std::endl;
626 pldm::utils::reportError(
627 "xyz.openbmc_project.bmc.pldm.InternalFailure");
628 return;
629 }
630
631 auto getStateSensorReadingRespHandler = [=, this](
632 mctp_eid_t /*eid*/,
633 const pldm_msg*
634 response,
635 size_t respMsgLen) {
636 if (response == nullptr || !respMsgLen)
637 {
638 std::cerr << "Failed to receive response for "
639 "getStateSensorReading command \n";
640 return;
641 }
642 std::array<get_sensor_state_field, 8> stateField{};
643 uint8_t completionCode = 0;
644 uint8_t comp_sensor_count = 0;
645
646 auto rc = decode_get_state_sensor_readings_resp(
647 response, respMsgLen, &completionCode,
648 &comp_sensor_count, stateField.data());
649
650 if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS)
651 {
652 std::cerr
653 << "Failed to "
654 "decode_get_state_sensor_readings_resp, rc = "
655 << rc
656 << " cc=" << static_cast<unsigned>(completionCode)
657 << std::endl;
658 pldm::utils::reportError(
659 "xyz.openbmc_project.bmc.pldm.InternalFailure");
660 }
661
662 uint8_t eventState;
663 uint8_t previousEventState;
664 uint8_t sensorOffset = comp_sensor_count - 1;
665
666 for (size_t i = 0; i < comp_sensor_count; i++)
667 {
668 eventState = stateField[i].present_state;
669 previousEventState = stateField[i].previous_state;
670
671 emitStateSensorEventSignal(tid, sensorId, sensorOffset,
672 eventState,
673 previousEventState);
674
675 SensorEntry sensorEntry{tid, sensorId};
676
677 pldm::pdr::EntityInfo entityInfo{};
678 pldm::pdr::CompositeSensorStates
679 compositeSensorStates{};
680
681 try
682 {
683 std::tie(entityInfo, compositeSensorStates) =
684 lookupSensorInfo(sensorEntry);
685 }
686 catch (const std::out_of_range& e)
687 {
688 try
689 {
690 sensorEntry.terminusID = PLDM_TID_RESERVED;
691 std::tie(entityInfo, compositeSensorStates) =
692 lookupSensorInfo(sensorEntry);
693 }
694 catch (const std::out_of_range& e)
695 {
696 std::cerr << "No mapping for the events"
697 << std::endl;
698 }
699 }
700
701 if (sensorOffset > compositeSensorStates.size())
702 {
703 std::cerr
704 << " Error Invalid data, Invalid sensor offset"
705 << std::endl;
706 return;
707 }
708
709 const auto& possibleStates =
710 compositeSensorStates[sensorOffset];
711 if (possibleStates.find(eventState) ==
712 possibleStates.end())
713 {
714 std::cerr
715 << " Error invalid_data, Invalid event state"
716 << std::endl;
717 return;
718 }
719 const auto& [containerId, entityType, entityInstance] =
720 entityInfo;
721 pldm::responder::events::StateSensorEntry
722 stateSensorEntry{containerId, entityType,
723 entityInstance, sensorOffset};
724 handleStateSensorEvent(stateSensorEntry, eventState);
725 }
726 };
727
728 rc = handler->registerRequest(
729 mctp_eid, instanceId, PLDM_PLATFORM,
730 PLDM_GET_STATE_SENSOR_READINGS, std::move(requestMsg),
731 std::move(getStateSensorReadingRespHandler));
732
733 if (rc != PLDM_SUCCESS)
734 {
735 std::cerr << " Failed to send request to get State sensor "
736 "reading on Host "
737 << std::endl;
738 }
739 }
740 }
741 }
742}
Pavithra Barithaya51efaf82020-04-02 02:42:27 -0500743} // namespace pldm