blob: 63512a3a9c05694a4b716c053f62ba9ef1d15051 [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 {
Manojkiran Eda60e1fe92021-10-08 15:58:16 +053090 // Delete all the remote terminus information
91 for (const auto& terminusInfo : this->tlPDRInfo)
92 {
93 if (terminusInfo.first != TERMINUS_HANDLE)
94 {
95 this->tlPDRInfo.erase(terminusInfo.first);
96 }
97 }
98
Deepak Kodihalli6b1d1ca2020-04-27 07:24:51 -050099 pldm_pdr_remove_remote_pdrs(repo);
Sampa Misrac073a202021-05-08 10:56:05 -0500100 pldm_entity_association_tree_destroy_root(entityTree);
101 pldm_entity_association_tree_copy_root(bmcEntityTree,
102 entityTree);
Tom Josephb4268602020-04-17 17:20:45 +0530103 this->sensorMap.clear();
Pavithra Barithaya23025b92021-09-28 05:22:52 -0500104 this->responseReceived = false;
Deepak Kodihalli6b1d1ca2020-04-27 07:24:51 -0500105 }
106 }
107 });
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500108}
109
Deepak Kodihalli7246e0c2020-07-08 06:40:18 -0500110void HostPDRHandler::fetchPDR(PDRRecordHandles&& recordHandles)
Pavithra Barithaya51efaf82020-04-02 02:42:27 -0500111{
Deepak Kodihalli8cb6f662020-04-10 02:55:43 -0500112 pdrRecordHandles.clear();
113 pdrRecordHandles = std::move(recordHandles);
114
115 // Defer the actual fetch of PDRs from the host (by queuing the call on the
116 // main event loop). That way, we can respond to the platform event msg from
117 // the host firmware.
118 pdrFetchEvent = std::make_unique<sdeventplus::source::Defer>(
119 event, std::bind(std::mem_fn(&HostPDRHandler::_fetchPDR), this,
120 std::placeholders::_1));
121}
122
123void HostPDRHandler::_fetchPDR(sdeventplus::source::EventBase& /*source*/)
124{
Sampa Misrac0c79482021-06-02 08:01:54 -0500125 getHostPDR();
126}
127
128void HostPDRHandler::getHostPDR(uint32_t nextRecordHandle)
129{
Deepak Kodihalli8cb6f662020-04-10 02:55:43 -0500130 pdrFetchEvent.reset();
131
Pavithra Barithaya51efaf82020-04-02 02:42:27 -0500132 std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) +
133 PLDM_GET_PDR_REQ_BYTES);
134 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
Deepak Kodihalli7246e0c2020-07-08 06:40:18 -0500135 uint32_t recordHandle{};
Sampa Misrac0c79482021-06-02 08:01:54 -0500136 if (!nextRecordHandle)
Deepak Kodihalli7246e0c2020-07-08 06:40:18 -0500137 {
Sampa Misrac0c79482021-06-02 08:01:54 -0500138 if (!pdrRecordHandles.empty())
139 {
140 recordHandle = pdrRecordHandles.front();
141 pdrRecordHandles.pop_front();
142 }
143 }
144 else
145 {
146 recordHandle = nextRecordHandle;
147 }
148 auto instanceId = requester.getInstanceId(mctp_eid);
149
150 auto rc =
151 encode_get_pdr_req(instanceId, recordHandle, 0, PLDM_GET_FIRSTPART,
152 UINT16_MAX, 0, request, PLDM_GET_PDR_REQ_BYTES);
153 if (rc != PLDM_SUCCESS)
154 {
155 requester.markFree(mctp_eid, instanceId);
156 std::cerr << "Failed to encode_get_pdr_req, rc = " << rc << std::endl;
157 return;
158 }
Deepak Kodihalli7246e0c2020-07-08 06:40:18 -0500159
Sampa Misrac0c79482021-06-02 08:01:54 -0500160 rc = handler->registerRequest(
161 mctp_eid, instanceId, PLDM_PLATFORM, PLDM_GET_PDR,
162 std::move(requestMsg),
163 std::move(std::bind_front(&HostPDRHandler::processHostPDRs, this)));
164 if (rc)
Pavithra Barithaya51efaf82020-04-02 02:42:27 -0500165 {
Sampa Misrac0c79482021-06-02 08:01:54 -0500166 std::cerr << "Failed to send the GetPDR request to Host \n";
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500167 }
Pavithra Barithaya51efaf82020-04-02 02:42:27 -0500168}
169
Pavithra Barithaya3aec9972020-12-14 01:55:44 -0600170int HostPDRHandler::handleStateSensorEvent(const StateSensorEntry& entry,
171 pdr::EventState state)
172{
173 auto rc = stateSensorHandler.eventAction(entry, state);
174 if (rc != PLDM_SUCCESS)
175 {
176 std::cerr << "Failed to fetch and update D-bus property, rc = " << rc
177 << std::endl;
178 return rc;
179 }
180 return PLDM_SUCCESS;
181}
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500182bool HostPDRHandler::getParent(EntityType type, pldm_entity& parent)
183{
184 auto found = parents.find(type);
185 if (found != parents.end())
186 {
187 parent.entity_type = found->second.entity_type;
188 parent.entity_instance_num = found->second.entity_instance_num;
189 return true;
190 }
191
192 return false;
193}
194
195void HostPDRHandler::mergeEntityAssociations(const std::vector<uint8_t>& pdr)
196{
197 size_t numEntities{};
198 pldm_entity* entities = nullptr;
199 bool merged = false;
200 auto entityPdr = reinterpret_cast<pldm_pdr_entity_association*>(
201 const_cast<uint8_t*>(pdr.data()) + sizeof(pldm_pdr_hdr));
202
203 pldm_entity_association_pdr_extract(pdr.data(), pdr.size(), &numEntities,
204 &entities);
205 for (size_t i = 0; i < numEntities; ++i)
206 {
207 pldm_entity parent{};
208 if (getParent(entities[i].entity_type, parent))
209 {
210 auto node = pldm_entity_association_tree_find(entityTree, &parent);
211 if (node)
212 {
George Liu64a8f0f2021-06-12 10:56:11 +0800213 pldm_entity_association_tree_add(entityTree, &entities[i],
214 0xFFFF, node,
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500215 entityPdr->association_type);
216 merged = true;
217 }
218 }
219 }
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500220
221 if (merged)
222 {
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500223 // Update our PDR repo with the merged entity association PDRs
Sampa Misra719ed392021-06-04 05:15:13 -0500224 pldm_entity_node* node = nullptr;
225 pldm_find_entity_ref_in_tree(entityTree, entities[0], &node);
226 if (node == nullptr)
227 {
228 std::cerr
229 << "\ncould not find referrence of the entity in the tree \n";
230 }
231 else
232 {
233 pldm_entity_association_pdr_add_from_node(node, repo, &entities,
234 numEntities, true);
235 }
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500236 }
Sampa Misra719ed392021-06-04 05:15:13 -0500237 free(entities);
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500238}
239
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500240void HostPDRHandler::sendPDRRepositoryChgEvent(std::vector<uint8_t>&& pdrTypes,
241 uint8_t eventDataFormat)
242{
243 assert(eventDataFormat == FORMAT_IS_PDR_HANDLES);
244
245 // Extract from the PDR repo record handles of PDRs we want the host
246 // to pull up.
247 std::vector<uint8_t> eventDataOps{PLDM_RECORDS_ADDED};
248 std::vector<uint8_t> numsOfChangeEntries(1);
249 std::vector<std::vector<ChangeEntry>> changeEntries(
250 numsOfChangeEntries.size());
251 for (auto pdrType : pdrTypes)
252 {
253 const pldm_pdr_record* record{};
254 do
255 {
256 record = pldm_pdr_find_record_by_type(repo, pdrType, record,
257 nullptr, nullptr);
258 if (record && pldm_pdr_record_is_remote(record))
259 {
260 changeEntries[0].push_back(
261 pldm_pdr_get_record_handle(repo, record));
262 }
263 } while (record);
264 }
265 if (changeEntries.empty())
266 {
267 return;
268 }
269 numsOfChangeEntries[0] = changeEntries[0].size();
270
271 // Encode PLDM platform event msg to indicate a PDR repo change.
272 size_t maxSize = PLDM_PDR_REPOSITORY_CHG_EVENT_MIN_LENGTH +
273 PLDM_PDR_REPOSITORY_CHANGE_RECORD_MIN_LENGTH +
274 changeEntries[0].size() * sizeof(uint32_t);
275 std::vector<uint8_t> eventDataVec{};
276 eventDataVec.resize(maxSize);
277 auto eventData =
278 reinterpret_cast<struct pldm_pdr_repository_chg_event_data*>(
279 eventDataVec.data());
280 size_t actualSize{};
281 auto firstEntry = changeEntries[0].data();
282 auto rc = encode_pldm_pdr_repository_chg_event_data(
283 eventDataFormat, 1, eventDataOps.data(), numsOfChangeEntries.data(),
284 &firstEntry, eventData, &actualSize, maxSize);
285 if (rc != PLDM_SUCCESS)
286 {
287 std::cerr
288 << "Failed to encode_pldm_pdr_repository_chg_event_data, rc = "
289 << rc << std::endl;
290 return;
291 }
292 auto instanceId = requester.getInstanceId(mctp_eid);
293 std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) +
294 PLDM_PLATFORM_EVENT_MESSAGE_MIN_REQ_BYTES +
295 actualSize);
296 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
297 rc = encode_platform_event_message_req(
298 instanceId, 1, 0, PLDM_PDR_REPOSITORY_CHG_EVENT, eventDataVec.data(),
Christian Geddes3bdb3c22020-05-01 14:55:39 -0500299 actualSize, request,
300 actualSize + PLDM_PLATFORM_EVENT_MESSAGE_MIN_REQ_BYTES);
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500301 if (rc != PLDM_SUCCESS)
302 {
303 requester.markFree(mctp_eid, instanceId);
304 std::cerr << "Failed to encode_platform_event_message_req, rc = " << rc
305 << std::endl;
306 return;
307 }
308
Tom Joseph74f27c72021-05-16 07:58:53 -0700309 auto platformEventMessageResponseHandler = [](mctp_eid_t /*eid*/,
310 const pldm_msg* response,
311 size_t respMsgLen) {
312 if (response == nullptr || !respMsgLen)
313 {
314 std::cerr << "Failed to receive response for the PDR repository "
315 "changed event"
316 << "\n";
317 return;
318 }
319
320 uint8_t completionCode{};
321 uint8_t status{};
322 auto responsePtr = reinterpret_cast<const struct pldm_msg*>(response);
Pavithra Barithaya54b5a562021-09-27 06:07:10 -0500323 auto rc = decode_platform_event_message_resp(responsePtr, respMsgLen,
324 &completionCode, &status);
Sampa Misrac0c79482021-06-02 08:01:54 -0500325 if (rc || completionCode)
Tom Joseph74f27c72021-05-16 07:58:53 -0700326 {
327 std::cerr << "Failed to decode_platform_event_message_resp: "
328 << "rc=" << rc
329 << ", cc=" << static_cast<unsigned>(completionCode)
330 << std::endl;
331 }
332 };
333
Sampa Misrac0c79482021-06-02 08:01:54 -0500334 rc = handler->registerRequest(
Sampa Misra626c5652021-08-11 10:28:48 -0500335 mctp_eid, instanceId, PLDM_PLATFORM, PLDM_PLATFORM_EVENT_MESSAGE,
Tom Joseph74f27c72021-05-16 07:58:53 -0700336 std::move(requestMsg), std::move(platformEventMessageResponseHandler));
Sampa Misrac0c79482021-06-02 08:01:54 -0500337 if (rc)
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500338 {
Tom Joseph74f27c72021-05-16 07:58:53 -0700339 std::cerr << "Failed to send the PDR repository changed event request"
340 << "\n";
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500341 }
342}
343
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530344void HostPDRHandler::parseStateSensorPDRs(const PDRList& stateSensorPDRs)
Sampa Misra868c8792020-05-26 03:12:13 -0500345{
346 for (const auto& pdr : stateSensorPDRs)
347 {
348 SensorEntry sensorEntry{};
349 const auto& [terminusHandle, sensorID, sensorInfo] =
350 responder::pdr_utils::parseStateSensorPDR(pdr);
351 sensorEntry.sensorID = sensorID;
352 try
353 {
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530354 sensorEntry.terminusID = std::get<0>(tlPDRInfo.at(terminusHandle));
Sampa Misra868c8792020-05-26 03:12:13 -0500355 }
356 // If there is no mapping for terminusHandle assign the reserved TID
357 // value of 0xFF to indicate that.
358 catch (const std::out_of_range& e)
359 {
360 sensorEntry.terminusID = PLDM_TID_RESERVED;
361 }
362 sensorMap.emplace(sensorEntry, std::move(sensorInfo));
363 }
364}
365
Sampa Misrac0c79482021-06-02 08:01:54 -0500366void HostPDRHandler::processHostPDRs(mctp_eid_t /*eid*/,
367 const pldm_msg* response,
368 size_t respMsgLen)
369{
370 static bool merged = false;
371 static PDRList stateSensorPDRs{};
Sampa Misrac0c79482021-06-02 08:01:54 -0500372 uint32_t nextRecordHandle{};
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600373 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));
Sampa Misrac0c79482021-06-02 08:01:54 -0500398 if (rc != PLDM_SUCCESS)
399 {
400 std::cerr << "Failed to decode_get_pdr_resp, rc = " << rc << std::endl;
401 return;
402 }
403 else
404 {
405 std::vector<uint8_t> pdr(respCount, 0);
406 rc = decode_get_pdr_resp(response, respMsgLen, &completionCode,
407 &nextRecordHandle, &nextDataTransferHandle,
408 &transferFlag, &respCount, pdr.data(),
409 respCount, &transferCRC);
410 if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS)
411 {
412 std::cerr << "Failed to decode_get_pdr_resp: "
413 << "rc=" << rc
414 << ", cc=" << static_cast<unsigned>(completionCode)
415 << std::endl;
416 return;
417 }
418 else
419 {
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600420 // when nextRecordHandle is 0, we need the recordHandle of the last
421 // PDR and not 0-1.
422 if (!nextRecordHandle)
423 {
424 rh = nextRecordHandle;
425 }
426 else
427 {
428 rh = nextRecordHandle - 1;
429 }
430
Sampa Misrac0c79482021-06-02 08:01:54 -0500431 auto pdrHdr = reinterpret_cast<pldm_pdr_hdr*>(pdr.data());
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600432 if (!rh)
433 {
434 rh = pdrHdr->record_handle;
435 }
436
Sampa Misrac0c79482021-06-02 08:01:54 -0500437 if (pdrHdr->type == PLDM_PDR_ENTITY_ASSOCIATION)
438 {
439 this->mergeEntityAssociations(pdr);
440 merged = true;
441 }
442 else
443 {
444 if (pdrHdr->type == PLDM_TERMINUS_LOCATOR_PDR)
445 {
446 auto tlpdr =
447 reinterpret_cast<const pldm_terminus_locator_pdr*>(
448 pdr.data());
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600449
450 terminusHandle = tlpdr->terminus_handle;
451 tid = tlpdr->tid;
452 auto terminus_locator_type = tlpdr->terminus_locator_type;
453 if (terminus_locator_type ==
454 PLDM_TERMINUS_LOCATOR_TYPE_MCTP_EID)
455 {
456 auto locatorValue = reinterpret_cast<
457 const pldm_terminus_locator_type_mctp_eid*>(
458 tlpdr->terminus_locator_value);
459 tlEid = static_cast<uint8_t>(locatorValue->eid);
460 }
461 if (tlpdr->validity == 0)
462 {
463 tlValid = false;
464 }
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530465 tlPDRInfo.insert_or_assign(
466 tlpdr->terminus_handle,
467 std::make_tuple(tlpdr->tid, tlEid, tlpdr->validity));
Sampa Misrac0c79482021-06-02 08:01:54 -0500468 }
469 else if (pdrHdr->type == PLDM_STATE_SENSOR_PDR)
470 {
471 stateSensorPDRs.emplace_back(pdr);
472 }
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600473
474 // if the TLPDR is invalid update the repo accordingly
475 if (!tlValid)
476 {
477 pldm_pdr_update_TL_pdr(repo, terminusHandle, tid, tlEid,
478 tlValid);
479 }
480 else
481 {
482 pldm_pdr_add(repo, pdr.data(), respCount, rh, true);
483 }
Sampa Misrac0c79482021-06-02 08:01:54 -0500484 }
485 }
486 }
487 if (!nextRecordHandle)
488 {
489 /*received last record*/
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530490 this->parseStateSensorPDRs(stateSensorPDRs);
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600491 if (isHostUp())
492 {
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530493 this->setHostSensorState(stateSensorPDRs);
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600494 }
Sampa Misrac0c79482021-06-02 08:01:54 -0500495 stateSensorPDRs.clear();
Sampa Misrac0c79482021-06-02 08:01:54 -0500496 if (merged)
497 {
498 merged = false;
499 deferredPDRRepoChgEvent =
500 std::make_unique<sdeventplus::source::Defer>(
501 event,
502 std::bind(
503 std::mem_fn((&HostPDRHandler::_processPDRRepoChgEvent)),
504 this, std::placeholders::_1));
505 }
506 }
507 else
508 {
509 deferredFetchPDREvent = std::make_unique<sdeventplus::source::Defer>(
510 event,
511 std::bind(std::mem_fn((&HostPDRHandler::_processFetchPDREvent)),
512 this, nextRecordHandle, std::placeholders::_1));
513 }
514}
515
516void HostPDRHandler::_processPDRRepoChgEvent(
517 sdeventplus::source::EventBase& /*source */)
518{
519 deferredPDRRepoChgEvent.reset();
520 this->sendPDRRepositoryChgEvent(
521 std::move(std::vector<uint8_t>(1, PLDM_PDR_ENTITY_ASSOCIATION)),
522 FORMAT_IS_PDR_HANDLES);
523}
524
525void HostPDRHandler::_processFetchPDREvent(
526 uint32_t nextRecordHandle, sdeventplus::source::EventBase& /*source */)
527{
528 deferredFetchPDREvent.reset();
529 if (!this->pdrRecordHandles.empty())
530 {
531 nextRecordHandle = this->pdrRecordHandles.front();
532 this->pdrRecordHandles.pop_front();
533 }
534 this->getHostPDR(nextRecordHandle);
535}
536
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500537void HostPDRHandler::setHostFirmwareCondition()
sampmisr6decfc12021-03-02 11:07:36 +0530538{
sampmisr6decfc12021-03-02 11:07:36 +0530539 responseReceived = false;
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500540 auto instanceId = requester.getInstanceId(mctp_eid);
541 std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) +
542 PLDM_GET_VERSION_REQ_BYTES);
543 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
544 auto rc = encode_get_version_req(instanceId, 0, PLDM_GET_FIRSTPART,
545 PLDM_BASE, request);
546 if (rc != PLDM_SUCCESS)
sampmisr6decfc12021-03-02 11:07:36 +0530547 {
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500548 std::cerr << "GetPLDMVersion encode failure. PLDM error code = "
549 << std::hex << std::showbase << rc << "\n";
550 requester.markFree(mctp_eid, instanceId);
sampmisr6decfc12021-03-02 11:07:36 +0530551 return;
552 }
553
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500554 auto getPLDMVersionHandler = [this](mctp_eid_t /*eid*/,
555 const pldm_msg* response,
556 size_t respMsgLen) {
557 if (response == nullptr || !respMsgLen)
sampmisr6decfc12021-03-02 11:07:36 +0530558 {
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500559 std::cerr << "Failed to receive response for "
560 << "getPLDMVersion command, Host seems to be off \n";
sampmisr6decfc12021-03-02 11:07:36 +0530561 return;
562 }
sampmisr6decfc12021-03-02 11:07:36 +0530563 std::cout << "Getting the response. PLDM RC = " << std::hex
564 << std::showbase
565 << static_cast<uint16_t>(response->payload[0]) << "\n";
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500566 this->responseReceived = true;
567 getHostPDR();
sampmisr6decfc12021-03-02 11:07:36 +0530568 };
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500569 rc = handler->registerRequest(mctp_eid, instanceId, PLDM_BASE,
570 PLDM_GET_PLDM_VERSION, std::move(requestMsg),
571 std::move(getPLDMVersionHandler));
572 if (rc)
sampmisr6decfc12021-03-02 11:07:36 +0530573 {
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500574 std::cerr << "Failed to discover Host state. Assuming Host as off \n";
sampmisr6decfc12021-03-02 11:07:36 +0530575 }
576}
577
578bool HostPDRHandler::isHostUp()
579{
580 return responseReceived;
581}
582
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530583void HostPDRHandler::setHostSensorState(const PDRList& stateSensorPDRs)
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600584{
585 for (const auto& stateSensorPDR : stateSensorPDRs)
586 {
587 auto pdr = reinterpret_cast<const pldm_state_sensor_pdr*>(
588 stateSensorPDR.data());
589
590 if (!pdr)
591 {
592 std::cerr << "Failed to get State sensor PDR" << std::endl;
593 pldm::utils::reportError(
594 "xyz.openbmc_project.bmc.pldm.InternalFailure");
595 return;
596 }
597
598 uint16_t sensorId = pdr->sensor_id;
599
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530600 for (const auto& [terminusHandle, terminusInfo] : tlPDRInfo)
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600601 {
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530602 if (terminusHandle == pdr->terminus_handle)
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600603 {
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530604 if (std::get<2>(terminusInfo) == PLDM_TL_PDR_VALID)
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600605 {
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530606 mctp_eid = std::get<1>(terminusInfo);
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600607 }
608
609 bitfield8_t sensorRearm;
610 sensorRearm.byte = 0;
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530611 uint8_t tid = std::get<0>(terminusInfo);
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600612
613 auto instanceId = requester.getInstanceId(mctp_eid);
614 std::vector<uint8_t> requestMsg(
615 sizeof(pldm_msg_hdr) +
616 PLDM_GET_STATE_SENSOR_READINGS_REQ_BYTES);
617 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
618 auto rc = encode_get_state_sensor_readings_req(
619 instanceId, sensorId, sensorRearm, 0, request);
620
621 if (rc != PLDM_SUCCESS)
622 {
623 requester.markFree(mctp_eid, instanceId);
624 std::cerr << "Failed to "
625 "encode_get_state_sensor_readings_req, rc = "
626 << rc << std::endl;
627 pldm::utils::reportError(
628 "xyz.openbmc_project.bmc.pldm.InternalFailure");
629 return;
630 }
631
632 auto getStateSensorReadingRespHandler = [=, this](
633 mctp_eid_t /*eid*/,
634 const pldm_msg*
635 response,
636 size_t respMsgLen) {
637 if (response == nullptr || !respMsgLen)
638 {
639 std::cerr << "Failed to receive response for "
640 "getStateSensorReading command \n";
641 return;
642 }
643 std::array<get_sensor_state_field, 8> stateField{};
644 uint8_t completionCode = 0;
645 uint8_t comp_sensor_count = 0;
646
647 auto rc = decode_get_state_sensor_readings_resp(
648 response, respMsgLen, &completionCode,
649 &comp_sensor_count, stateField.data());
650
651 if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS)
652 {
653 std::cerr
654 << "Failed to "
655 "decode_get_state_sensor_readings_resp, rc = "
656 << rc
657 << " cc=" << static_cast<unsigned>(completionCode)
658 << std::endl;
659 pldm::utils::reportError(
660 "xyz.openbmc_project.bmc.pldm.InternalFailure");
661 }
662
663 uint8_t eventState;
664 uint8_t previousEventState;
665 uint8_t sensorOffset = comp_sensor_count - 1;
666
667 for (size_t i = 0; i < comp_sensor_count; i++)
668 {
669 eventState = stateField[i].present_state;
670 previousEventState = stateField[i].previous_state;
671
672 emitStateSensorEventSignal(tid, sensorId, sensorOffset,
673 eventState,
674 previousEventState);
675
676 SensorEntry sensorEntry{tid, sensorId};
677
678 pldm::pdr::EntityInfo entityInfo{};
679 pldm::pdr::CompositeSensorStates
680 compositeSensorStates{};
681
682 try
683 {
684 std::tie(entityInfo, compositeSensorStates) =
685 lookupSensorInfo(sensorEntry);
686 }
687 catch (const std::out_of_range& e)
688 {
689 try
690 {
691 sensorEntry.terminusID = PLDM_TID_RESERVED;
692 std::tie(entityInfo, compositeSensorStates) =
693 lookupSensorInfo(sensorEntry);
694 }
695 catch (const std::out_of_range& e)
696 {
697 std::cerr << "No mapping for the events"
698 << std::endl;
699 }
700 }
701
702 if (sensorOffset > compositeSensorStates.size())
703 {
704 std::cerr
705 << " Error Invalid data, Invalid sensor offset"
706 << std::endl;
707 return;
708 }
709
710 const auto& possibleStates =
711 compositeSensorStates[sensorOffset];
712 if (possibleStates.find(eventState) ==
713 possibleStates.end())
714 {
715 std::cerr
716 << " Error invalid_data, Invalid event state"
717 << std::endl;
718 return;
719 }
720 const auto& [containerId, entityType, entityInstance] =
721 entityInfo;
722 pldm::responder::events::StateSensorEntry
723 stateSensorEntry{containerId, entityType,
724 entityInstance, sensorOffset};
725 handleStateSensorEvent(stateSensorEntry, eventState);
726 }
727 };
728
729 rc = handler->registerRequest(
730 mctp_eid, instanceId, PLDM_PLATFORM,
731 PLDM_GET_STATE_SENSOR_READINGS, std::move(requestMsg),
732 std::move(getStateSensorReadingRespHandler));
733
734 if (rc != PLDM_SUCCESS)
735 {
736 std::cerr << " Failed to send request to get State sensor "
737 "reading on Host "
738 << std::endl;
739 }
740 }
741 }
742 }
743}
Pavithra Barithaya51efaf82020-04-02 02:42:27 -0500744} // namespace pldm