blob: f23407b2e0053932a72d30c9fbb31064823df15b [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
Manojkiran Eda8fee19a2021-11-15 12:07:44 +053091 std::erase_if(tlPDRInfo, [](const auto& item) {
92 auto const& [key, value] = item;
93 return key != TERMINUS_HANDLE;
94 });
Deepak Kodihalli6b1d1ca2020-04-27 07:24:51 -050095 pldm_pdr_remove_remote_pdrs(repo);
Sampa Misrac073a202021-05-08 10:56:05 -050096 pldm_entity_association_tree_destroy_root(entityTree);
97 pldm_entity_association_tree_copy_root(bmcEntityTree,
98 entityTree);
Tom Josephb4268602020-04-17 17:20:45 +053099 this->sensorMap.clear();
Pavithra Barithaya23025b92021-09-28 05:22:52 -0500100 this->responseReceived = false;
Deepak Kodihalli6b1d1ca2020-04-27 07:24:51 -0500101 }
102 }
103 });
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500104}
105
Deepak Kodihalli7246e0c2020-07-08 06:40:18 -0500106void HostPDRHandler::fetchPDR(PDRRecordHandles&& recordHandles)
Pavithra Barithaya51efaf82020-04-02 02:42:27 -0500107{
Deepak Kodihalli8cb6f662020-04-10 02:55:43 -0500108 pdrRecordHandles.clear();
109 pdrRecordHandles = std::move(recordHandles);
110
111 // Defer the actual fetch of PDRs from the host (by queuing the call on the
112 // main event loop). That way, we can respond to the platform event msg from
113 // the host firmware.
114 pdrFetchEvent = std::make_unique<sdeventplus::source::Defer>(
115 event, std::bind(std::mem_fn(&HostPDRHandler::_fetchPDR), this,
116 std::placeholders::_1));
117}
118
119void HostPDRHandler::_fetchPDR(sdeventplus::source::EventBase& /*source*/)
120{
Sampa Misrac0c79482021-06-02 08:01:54 -0500121 getHostPDR();
122}
123
124void HostPDRHandler::getHostPDR(uint32_t nextRecordHandle)
125{
Deepak Kodihalli8cb6f662020-04-10 02:55:43 -0500126 pdrFetchEvent.reset();
127
Pavithra Barithaya51efaf82020-04-02 02:42:27 -0500128 std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) +
129 PLDM_GET_PDR_REQ_BYTES);
130 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
Deepak Kodihalli7246e0c2020-07-08 06:40:18 -0500131 uint32_t recordHandle{};
Sampa Misrac0c79482021-06-02 08:01:54 -0500132 if (!nextRecordHandle)
Deepak Kodihalli7246e0c2020-07-08 06:40:18 -0500133 {
Sampa Misrac0c79482021-06-02 08:01:54 -0500134 if (!pdrRecordHandles.empty())
135 {
136 recordHandle = pdrRecordHandles.front();
137 pdrRecordHandles.pop_front();
138 }
139 }
140 else
141 {
142 recordHandle = nextRecordHandle;
143 }
144 auto instanceId = requester.getInstanceId(mctp_eid);
145
146 auto rc =
147 encode_get_pdr_req(instanceId, recordHandle, 0, PLDM_GET_FIRSTPART,
148 UINT16_MAX, 0, request, PLDM_GET_PDR_REQ_BYTES);
149 if (rc != PLDM_SUCCESS)
150 {
151 requester.markFree(mctp_eid, instanceId);
152 std::cerr << "Failed to encode_get_pdr_req, rc = " << rc << std::endl;
153 return;
154 }
Deepak Kodihalli7246e0c2020-07-08 06:40:18 -0500155
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);
Pavithra Barithaya54b5a562021-09-27 06:07:10 -0500319 auto rc = decode_platform_event_message_resp(responsePtr, respMsgLen,
320 &completionCode, &status);
Sampa Misrac0c79482021-06-02 08:01:54 -0500321 if (rc || completionCode)
Tom Joseph74f27c72021-05-16 07:58:53 -0700322 {
323 std::cerr << "Failed to decode_platform_event_message_resp: "
324 << "rc=" << rc
325 << ", cc=" << static_cast<unsigned>(completionCode)
326 << std::endl;
327 }
328 };
329
Sampa Misrac0c79482021-06-02 08:01:54 -0500330 rc = handler->registerRequest(
Sampa Misra626c5652021-08-11 10:28:48 -0500331 mctp_eid, instanceId, PLDM_PLATFORM, PLDM_PLATFORM_EVENT_MESSAGE,
Tom Joseph74f27c72021-05-16 07:58:53 -0700332 std::move(requestMsg), std::move(platformEventMessageResponseHandler));
Sampa Misrac0c79482021-06-02 08:01:54 -0500333 if (rc)
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500334 {
Tom Joseph74f27c72021-05-16 07:58:53 -0700335 std::cerr << "Failed to send the PDR repository changed event request"
336 << "\n";
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500337 }
338}
339
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530340void HostPDRHandler::parseStateSensorPDRs(const PDRList& stateSensorPDRs)
Sampa Misra868c8792020-05-26 03:12:13 -0500341{
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 {
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530350 sensorEntry.terminusID = std::get<0>(tlPDRInfo.at(terminusHandle));
Sampa Misra868c8792020-05-26 03:12:13 -0500351 }
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{};
Sampa Misrac0c79482021-06-02 08:01:54 -0500368 uint32_t nextRecordHandle{};
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600369 uint8_t tlEid = 0;
370 bool tlValid = true;
371 uint32_t rh = 0;
372 uint16_t terminusHandle = 0;
373 uint8_t tid = 0;
374
Sampa Misrac0c79482021-06-02 08:01:54 -0500375 uint8_t completionCode{};
376 uint32_t nextDataTransferHandle{};
377 uint8_t transferFlag{};
378 uint16_t respCount{};
379 uint8_t transferCRC{};
380 if (response == nullptr || !respMsgLen)
381 {
382 std::cerr << "Failed to receive response for the GetPDR"
383 " command \n";
384 return;
385 }
386
387 auto rc = decode_get_pdr_resp(
388 response, respMsgLen /*- sizeof(pldm_msg_hdr)*/, &completionCode,
389 &nextRecordHandle, &nextDataTransferHandle, &transferFlag, &respCount,
390 nullptr, 0, &transferCRC);
391 std::vector<uint8_t> responsePDRMsg;
392 responsePDRMsg.resize(respMsgLen + sizeof(pldm_msg_hdr));
393 memcpy(responsePDRMsg.data(), response, respMsgLen + sizeof(pldm_msg_hdr));
Sampa Misrac0c79482021-06-02 08:01:54 -0500394 if (rc != PLDM_SUCCESS)
395 {
396 std::cerr << "Failed to decode_get_pdr_resp, rc = " << rc << std::endl;
397 return;
398 }
399 else
400 {
401 std::vector<uint8_t> pdr(respCount, 0);
402 rc = decode_get_pdr_resp(response, respMsgLen, &completionCode,
403 &nextRecordHandle, &nextDataTransferHandle,
404 &transferFlag, &respCount, pdr.data(),
405 respCount, &transferCRC);
406 if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS)
407 {
408 std::cerr << "Failed to decode_get_pdr_resp: "
409 << "rc=" << rc
410 << ", cc=" << static_cast<unsigned>(completionCode)
411 << std::endl;
412 return;
413 }
414 else
415 {
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600416 // when nextRecordHandle is 0, we need the recordHandle of the last
417 // PDR and not 0-1.
418 if (!nextRecordHandle)
419 {
420 rh = nextRecordHandle;
421 }
422 else
423 {
424 rh = nextRecordHandle - 1;
425 }
426
Sampa Misrac0c79482021-06-02 08:01:54 -0500427 auto pdrHdr = reinterpret_cast<pldm_pdr_hdr*>(pdr.data());
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600428 if (!rh)
429 {
430 rh = pdrHdr->record_handle;
431 }
432
Sampa Misrac0c79482021-06-02 08:01:54 -0500433 if (pdrHdr->type == PLDM_PDR_ENTITY_ASSOCIATION)
434 {
435 this->mergeEntityAssociations(pdr);
436 merged = true;
437 }
438 else
439 {
440 if (pdrHdr->type == PLDM_TERMINUS_LOCATOR_PDR)
441 {
442 auto tlpdr =
443 reinterpret_cast<const pldm_terminus_locator_pdr*>(
444 pdr.data());
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600445
446 terminusHandle = tlpdr->terminus_handle;
447 tid = tlpdr->tid;
448 auto terminus_locator_type = tlpdr->terminus_locator_type;
449 if (terminus_locator_type ==
450 PLDM_TERMINUS_LOCATOR_TYPE_MCTP_EID)
451 {
452 auto locatorValue = reinterpret_cast<
453 const pldm_terminus_locator_type_mctp_eid*>(
454 tlpdr->terminus_locator_value);
455 tlEid = static_cast<uint8_t>(locatorValue->eid);
456 }
457 if (tlpdr->validity == 0)
458 {
459 tlValid = false;
460 }
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530461 tlPDRInfo.insert_or_assign(
462 tlpdr->terminus_handle,
463 std::make_tuple(tlpdr->tid, tlEid, tlpdr->validity));
Sampa Misrac0c79482021-06-02 08:01:54 -0500464 }
465 else if (pdrHdr->type == PLDM_STATE_SENSOR_PDR)
466 {
467 stateSensorPDRs.emplace_back(pdr);
468 }
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600469
470 // if the TLPDR is invalid update the repo accordingly
471 if (!tlValid)
472 {
473 pldm_pdr_update_TL_pdr(repo, terminusHandle, tid, tlEid,
474 tlValid);
475 }
476 else
477 {
478 pldm_pdr_add(repo, pdr.data(), respCount, rh, true);
479 }
Sampa Misrac0c79482021-06-02 08:01:54 -0500480 }
481 }
482 }
483 if (!nextRecordHandle)
484 {
485 /*received last record*/
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530486 this->parseStateSensorPDRs(stateSensorPDRs);
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600487 if (isHostUp())
488 {
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530489 this->setHostSensorState(stateSensorPDRs);
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600490 }
Sampa Misrac0c79482021-06-02 08:01:54 -0500491 stateSensorPDRs.clear();
Sampa Misrac0c79482021-06-02 08:01:54 -0500492 if (merged)
493 {
494 merged = false;
495 deferredPDRRepoChgEvent =
496 std::make_unique<sdeventplus::source::Defer>(
497 event,
498 std::bind(
499 std::mem_fn((&HostPDRHandler::_processPDRRepoChgEvent)),
500 this, std::placeholders::_1));
501 }
502 }
503 else
504 {
505 deferredFetchPDREvent = std::make_unique<sdeventplus::source::Defer>(
506 event,
507 std::bind(std::mem_fn((&HostPDRHandler::_processFetchPDREvent)),
508 this, nextRecordHandle, std::placeholders::_1));
509 }
510}
511
512void HostPDRHandler::_processPDRRepoChgEvent(
513 sdeventplus::source::EventBase& /*source */)
514{
515 deferredPDRRepoChgEvent.reset();
516 this->sendPDRRepositoryChgEvent(
517 std::move(std::vector<uint8_t>(1, PLDM_PDR_ENTITY_ASSOCIATION)),
518 FORMAT_IS_PDR_HANDLES);
519}
520
521void HostPDRHandler::_processFetchPDREvent(
522 uint32_t nextRecordHandle, sdeventplus::source::EventBase& /*source */)
523{
524 deferredFetchPDREvent.reset();
525 if (!this->pdrRecordHandles.empty())
526 {
527 nextRecordHandle = this->pdrRecordHandles.front();
528 this->pdrRecordHandles.pop_front();
529 }
530 this->getHostPDR(nextRecordHandle);
531}
532
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500533void HostPDRHandler::setHostFirmwareCondition()
sampmisr6decfc12021-03-02 11:07:36 +0530534{
sampmisr6decfc12021-03-02 11:07:36 +0530535 responseReceived = false;
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500536 auto instanceId = requester.getInstanceId(mctp_eid);
537 std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) +
538 PLDM_GET_VERSION_REQ_BYTES);
539 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
540 auto rc = encode_get_version_req(instanceId, 0, PLDM_GET_FIRSTPART,
541 PLDM_BASE, request);
542 if (rc != PLDM_SUCCESS)
sampmisr6decfc12021-03-02 11:07:36 +0530543 {
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500544 std::cerr << "GetPLDMVersion encode failure. PLDM error code = "
545 << std::hex << std::showbase << rc << "\n";
546 requester.markFree(mctp_eid, instanceId);
sampmisr6decfc12021-03-02 11:07:36 +0530547 return;
548 }
549
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500550 auto getPLDMVersionHandler = [this](mctp_eid_t /*eid*/,
551 const pldm_msg* response,
552 size_t respMsgLen) {
553 if (response == nullptr || !respMsgLen)
sampmisr6decfc12021-03-02 11:07:36 +0530554 {
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500555 std::cerr << "Failed to receive response for "
556 << "getPLDMVersion command, Host seems to be off \n";
sampmisr6decfc12021-03-02 11:07:36 +0530557 return;
558 }
sampmisr6decfc12021-03-02 11:07:36 +0530559 std::cout << "Getting the response. PLDM RC = " << std::hex
560 << std::showbase
561 << static_cast<uint16_t>(response->payload[0]) << "\n";
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500562 this->responseReceived = true;
563 getHostPDR();
sampmisr6decfc12021-03-02 11:07:36 +0530564 };
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500565 rc = handler->registerRequest(mctp_eid, instanceId, PLDM_BASE,
566 PLDM_GET_PLDM_VERSION, std::move(requestMsg),
567 std::move(getPLDMVersionHandler));
568 if (rc)
sampmisr6decfc12021-03-02 11:07:36 +0530569 {
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500570 std::cerr << "Failed to discover Host state. Assuming Host as off \n";
sampmisr6decfc12021-03-02 11:07:36 +0530571 }
572}
573
574bool HostPDRHandler::isHostUp()
575{
576 return responseReceived;
577}
578
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530579void HostPDRHandler::setHostSensorState(const PDRList& stateSensorPDRs)
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600580{
581 for (const auto& stateSensorPDR : stateSensorPDRs)
582 {
583 auto pdr = reinterpret_cast<const pldm_state_sensor_pdr*>(
584 stateSensorPDR.data());
585
586 if (!pdr)
587 {
588 std::cerr << "Failed to get State sensor PDR" << std::endl;
589 pldm::utils::reportError(
590 "xyz.openbmc_project.bmc.pldm.InternalFailure");
591 return;
592 }
593
594 uint16_t sensorId = pdr->sensor_id;
595
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530596 for (const auto& [terminusHandle, terminusInfo] : tlPDRInfo)
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600597 {
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530598 if (terminusHandle == pdr->terminus_handle)
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600599 {
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530600 if (std::get<2>(terminusInfo) == PLDM_TL_PDR_VALID)
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600601 {
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530602 mctp_eid = std::get<1>(terminusInfo);
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600603 }
604
605 bitfield8_t sensorRearm;
606 sensorRearm.byte = 0;
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530607 uint8_t tid = std::get<0>(terminusInfo);
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600608
609 auto instanceId = requester.getInstanceId(mctp_eid);
610 std::vector<uint8_t> requestMsg(
611 sizeof(pldm_msg_hdr) +
612 PLDM_GET_STATE_SENSOR_READINGS_REQ_BYTES);
613 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
614 auto rc = encode_get_state_sensor_readings_req(
615 instanceId, sensorId, sensorRearm, 0, request);
616
617 if (rc != PLDM_SUCCESS)
618 {
619 requester.markFree(mctp_eid, instanceId);
620 std::cerr << "Failed to "
621 "encode_get_state_sensor_readings_req, rc = "
622 << rc << std::endl;
623 pldm::utils::reportError(
624 "xyz.openbmc_project.bmc.pldm.InternalFailure");
625 return;
626 }
627
628 auto getStateSensorReadingRespHandler = [=, this](
629 mctp_eid_t /*eid*/,
630 const pldm_msg*
631 response,
632 size_t respMsgLen) {
633 if (response == nullptr || !respMsgLen)
634 {
635 std::cerr << "Failed to receive response for "
636 "getStateSensorReading command \n";
637 return;
638 }
639 std::array<get_sensor_state_field, 8> stateField{};
640 uint8_t completionCode = 0;
641 uint8_t comp_sensor_count = 0;
642
643 auto rc = decode_get_state_sensor_readings_resp(
644 response, respMsgLen, &completionCode,
645 &comp_sensor_count, stateField.data());
646
647 if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS)
648 {
649 std::cerr
650 << "Failed to "
651 "decode_get_state_sensor_readings_resp, rc = "
652 << rc
653 << " cc=" << static_cast<unsigned>(completionCode)
654 << std::endl;
655 pldm::utils::reportError(
656 "xyz.openbmc_project.bmc.pldm.InternalFailure");
657 }
658
659 uint8_t eventState;
660 uint8_t previousEventState;
661 uint8_t sensorOffset = comp_sensor_count - 1;
662
663 for (size_t i = 0; i < comp_sensor_count; i++)
664 {
665 eventState = stateField[i].present_state;
666 previousEventState = stateField[i].previous_state;
667
668 emitStateSensorEventSignal(tid, sensorId, sensorOffset,
669 eventState,
670 previousEventState);
671
672 SensorEntry sensorEntry{tid, sensorId};
673
674 pldm::pdr::EntityInfo entityInfo{};
675 pldm::pdr::CompositeSensorStates
676 compositeSensorStates{};
677
678 try
679 {
680 std::tie(entityInfo, compositeSensorStates) =
681 lookupSensorInfo(sensorEntry);
682 }
683 catch (const std::out_of_range& e)
684 {
685 try
686 {
687 sensorEntry.terminusID = PLDM_TID_RESERVED;
688 std::tie(entityInfo, compositeSensorStates) =
689 lookupSensorInfo(sensorEntry);
690 }
691 catch (const std::out_of_range& e)
692 {
693 std::cerr << "No mapping for the events"
694 << std::endl;
695 }
696 }
697
698 if (sensorOffset > compositeSensorStates.size())
699 {
700 std::cerr
701 << " Error Invalid data, Invalid sensor offset"
702 << std::endl;
703 return;
704 }
705
706 const auto& possibleStates =
707 compositeSensorStates[sensorOffset];
708 if (possibleStates.find(eventState) ==
709 possibleStates.end())
710 {
711 std::cerr
712 << " Error invalid_data, Invalid event state"
713 << std::endl;
714 return;
715 }
716 const auto& [containerId, entityType, entityInstance] =
717 entityInfo;
718 pldm::responder::events::StateSensorEntry
719 stateSensorEntry{containerId, entityType,
720 entityInstance, sensorOffset};
721 handleStateSensorEvent(stateSensorEntry, eventState);
722 }
723 };
724
725 rc = handler->registerRequest(
726 mctp_eid, instanceId, PLDM_PLATFORM,
727 PLDM_GET_STATE_SENSOR_READINGS, std::move(requestMsg),
728 std::move(getStateSensorReadingRespHandler));
729
730 if (rc != PLDM_SUCCESS)
731 {
732 std::cerr << " Failed to send request to get State sensor "
733 "reading on Host "
734 << std::endl;
735 }
736 }
737 }
738 }
739}
Pavithra Barithaya51efaf82020-04-02 02:42:27 -0500740} // namespace pldm