blob: f4c86e6840363475191ffece3f0b85cad5efb833 [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
Manojkiran Eda3ca40452021-10-04 22:51:37 +053030template <typename T>
31uint16_t extractTerminusHandle(std::vector<uint8_t>& pdr)
32{
33 T* var = nullptr;
34 if (std::is_same<T, pldm_pdr_fru_record_set>::value)
35 {
36 var = (T*)(pdr.data() + sizeof(pldm_pdr_hdr));
37 }
38 else
39 {
40 var = (T*)(pdr.data());
41 }
42 if (var != nullptr)
43 {
44 return var->terminus_handle;
45 }
46 return TERMINUS_HANDLE;
47}
48
Tom Joseph74f27c72021-05-16 07:58:53 -070049HostPDRHandler::HostPDRHandler(
50 int mctp_fd, uint8_t mctp_eid, sdeventplus::Event& event, pldm_pdr* repo,
51 const std::string& eventsJsonsDir, pldm_entity_association_tree* entityTree,
52 pldm_entity_association_tree* bmcEntityTree, Requester& requester,
Tom Josephe5268cd2021-09-07 13:04:03 +053053 pldm::requester::Handler<pldm::requester::Request>* handler) :
Deepak Kodihalli87514cc2020-04-16 09:08:38 -050054 mctp_fd(mctp_fd),
Pavithra Barithaya3aec9972020-12-14 01:55:44 -060055 mctp_eid(mctp_eid), event(event), repo(repo),
56 stateSensorHandler(eventsJsonsDir), entityTree(entityTree),
Tom Josephe5268cd2021-09-07 13:04:03 +053057 bmcEntityTree(bmcEntityTree), requester(requester), handler(handler)
Deepak Kodihalli87514cc2020-04-16 09:08:38 -050058{
59 fs::path hostFruJson(fs::path(HOST_JSONS_DIR) / fruJson);
60 if (fs::exists(hostFruJson))
61 {
Pavithra Barithayae8beb892020-04-14 23:24:25 -050062 // Note parent entities for entities sent down by the host firmware.
63 // This will enable a merge of entity associations.
Deepak Kodihalli87514cc2020-04-16 09:08:38 -050064 try
65 {
66 std::ifstream jsonFile(hostFruJson);
67 auto data = Json::parse(jsonFile, nullptr, false);
68 if (data.is_discarded())
69 {
70 std::cerr << "Parsing Host FRU json file failed" << std::endl;
71 }
72 else
73 {
74 auto entities = data.value("entities", emptyJsonList);
75 for (auto& entity : entities)
76 {
77 EntityType entityType = entity.value("entity_type", 0);
78 auto parent = entity.value("parent", emptyJson);
79 pldm_entity p{};
80 p.entity_type = parent.value("entity_type", 0);
81 p.entity_instance_num = parent.value("entity_instance", 0);
82 parents.emplace(entityType, std::move(p));
83 }
84 }
85 }
86 catch (const std::exception& e)
87 {
88 std::cerr << "Parsing Host FRU json file failed, exception = "
89 << e.what() << std::endl;
90 }
91 }
Deepak Kodihalli6b1d1ca2020-04-27 07:24:51 -050092
93 hostOffMatch = std::make_unique<sdbusplus::bus::match::match>(
94 pldm::utils::DBusHandler::getBus(),
95 propertiesChanged("/xyz/openbmc_project/state/host0",
96 "xyz.openbmc_project.State.Host"),
Sampa Misrac073a202021-05-08 10:56:05 -050097 [this, repo, entityTree,
98 bmcEntityTree](sdbusplus::message::message& msg) {
Deepak Kodihalli6b1d1ca2020-04-27 07:24:51 -050099 DbusChangedProps props{};
100 std::string intf;
101 msg.read(intf, props);
102 const auto itr = props.find("CurrentHostState");
103 if (itr != props.end())
104 {
105 PropertyValue value = itr->second;
106 auto propVal = std::get<std::string>(value);
107 if (propVal == "xyz.openbmc_project.State.Host.HostState.Off")
108 {
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530109 // Delete all the remote terminus information
Manojkiran Eda8fee19a2021-11-15 12:07:44 +0530110 std::erase_if(tlPDRInfo, [](const auto& item) {
111 auto const& [key, value] = item;
112 return key != TERMINUS_HANDLE;
113 });
Deepak Kodihalli6b1d1ca2020-04-27 07:24:51 -0500114 pldm_pdr_remove_remote_pdrs(repo);
Sampa Misrac073a202021-05-08 10:56:05 -0500115 pldm_entity_association_tree_destroy_root(entityTree);
116 pldm_entity_association_tree_copy_root(bmcEntityTree,
117 entityTree);
Tom Josephb4268602020-04-17 17:20:45 +0530118 this->sensorMap.clear();
Pavithra Barithaya23025b92021-09-28 05:22:52 -0500119 this->responseReceived = false;
Deepak Kodihalli6b1d1ca2020-04-27 07:24:51 -0500120 }
121 }
122 });
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500123}
124
Deepak Kodihalli7246e0c2020-07-08 06:40:18 -0500125void HostPDRHandler::fetchPDR(PDRRecordHandles&& recordHandles)
Pavithra Barithaya51efaf82020-04-02 02:42:27 -0500126{
Deepak Kodihalli8cb6f662020-04-10 02:55:43 -0500127 pdrRecordHandles.clear();
128 pdrRecordHandles = std::move(recordHandles);
129
130 // Defer the actual fetch of PDRs from the host (by queuing the call on the
131 // main event loop). That way, we can respond to the platform event msg from
132 // the host firmware.
133 pdrFetchEvent = std::make_unique<sdeventplus::source::Defer>(
134 event, std::bind(std::mem_fn(&HostPDRHandler::_fetchPDR), this,
135 std::placeholders::_1));
136}
137
138void HostPDRHandler::_fetchPDR(sdeventplus::source::EventBase& /*source*/)
139{
Sampa Misrac0c79482021-06-02 08:01:54 -0500140 getHostPDR();
141}
142
143void HostPDRHandler::getHostPDR(uint32_t nextRecordHandle)
144{
Deepak Kodihalli8cb6f662020-04-10 02:55:43 -0500145 pdrFetchEvent.reset();
146
Pavithra Barithaya51efaf82020-04-02 02:42:27 -0500147 std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) +
148 PLDM_GET_PDR_REQ_BYTES);
149 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
Deepak Kodihalli7246e0c2020-07-08 06:40:18 -0500150 uint32_t recordHandle{};
Sampa Misrac0c79482021-06-02 08:01:54 -0500151 if (!nextRecordHandle)
Deepak Kodihalli7246e0c2020-07-08 06:40:18 -0500152 {
Sampa Misrac0c79482021-06-02 08:01:54 -0500153 if (!pdrRecordHandles.empty())
154 {
155 recordHandle = pdrRecordHandles.front();
156 pdrRecordHandles.pop_front();
157 }
158 }
159 else
160 {
161 recordHandle = nextRecordHandle;
162 }
163 auto instanceId = requester.getInstanceId(mctp_eid);
164
165 auto rc =
166 encode_get_pdr_req(instanceId, recordHandle, 0, PLDM_GET_FIRSTPART,
167 UINT16_MAX, 0, request, PLDM_GET_PDR_REQ_BYTES);
168 if (rc != PLDM_SUCCESS)
169 {
170 requester.markFree(mctp_eid, instanceId);
171 std::cerr << "Failed to encode_get_pdr_req, rc = " << rc << std::endl;
172 return;
173 }
Deepak Kodihalli7246e0c2020-07-08 06:40:18 -0500174
Sampa Misrac0c79482021-06-02 08:01:54 -0500175 rc = handler->registerRequest(
176 mctp_eid, instanceId, PLDM_PLATFORM, PLDM_GET_PDR,
177 std::move(requestMsg),
178 std::move(std::bind_front(&HostPDRHandler::processHostPDRs, this)));
179 if (rc)
Pavithra Barithaya51efaf82020-04-02 02:42:27 -0500180 {
Sampa Misrac0c79482021-06-02 08:01:54 -0500181 std::cerr << "Failed to send the GetPDR request to Host \n";
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500182 }
Pavithra Barithaya51efaf82020-04-02 02:42:27 -0500183}
184
Pavithra Barithaya3aec9972020-12-14 01:55:44 -0600185int HostPDRHandler::handleStateSensorEvent(const StateSensorEntry& entry,
186 pdr::EventState state)
187{
188 auto rc = stateSensorHandler.eventAction(entry, state);
189 if (rc != PLDM_SUCCESS)
190 {
191 std::cerr << "Failed to fetch and update D-bus property, rc = " << rc
192 << std::endl;
193 return rc;
194 }
195 return PLDM_SUCCESS;
196}
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500197bool HostPDRHandler::getParent(EntityType type, pldm_entity& parent)
198{
199 auto found = parents.find(type);
200 if (found != parents.end())
201 {
202 parent.entity_type = found->second.entity_type;
203 parent.entity_instance_num = found->second.entity_instance_num;
204 return true;
205 }
206
207 return false;
208}
209
210void HostPDRHandler::mergeEntityAssociations(const std::vector<uint8_t>& pdr)
211{
212 size_t numEntities{};
213 pldm_entity* entities = nullptr;
214 bool merged = false;
215 auto entityPdr = reinterpret_cast<pldm_pdr_entity_association*>(
216 const_cast<uint8_t*>(pdr.data()) + sizeof(pldm_pdr_hdr));
217
218 pldm_entity_association_pdr_extract(pdr.data(), pdr.size(), &numEntities,
219 &entities);
220 for (size_t i = 0; i < numEntities; ++i)
221 {
222 pldm_entity parent{};
223 if (getParent(entities[i].entity_type, parent))
224 {
225 auto node = pldm_entity_association_tree_find(entityTree, &parent);
226 if (node)
227 {
George Liu64a8f0f2021-06-12 10:56:11 +0800228 pldm_entity_association_tree_add(entityTree, &entities[i],
229 0xFFFF, node,
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500230 entityPdr->association_type);
231 merged = true;
232 }
233 }
234 }
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500235
236 if (merged)
237 {
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500238 // Update our PDR repo with the merged entity association PDRs
Sampa Misra719ed392021-06-04 05:15:13 -0500239 pldm_entity_node* node = nullptr;
240 pldm_find_entity_ref_in_tree(entityTree, entities[0], &node);
241 if (node == nullptr)
242 {
243 std::cerr
244 << "\ncould not find referrence of the entity in the tree \n";
245 }
246 else
247 {
Manojkiran Eda3ca40452021-10-04 22:51:37 +0530248 pldm_entity_association_pdr_add_from_node(
249 node, repo, &entities, numEntities, true, TERMINUS_HANDLE);
Sampa Misra719ed392021-06-04 05:15:13 -0500250 }
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500251 }
Sampa Misra719ed392021-06-04 05:15:13 -0500252 free(entities);
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500253}
254
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500255void HostPDRHandler::sendPDRRepositoryChgEvent(std::vector<uint8_t>&& pdrTypes,
256 uint8_t eventDataFormat)
257{
258 assert(eventDataFormat == FORMAT_IS_PDR_HANDLES);
259
260 // Extract from the PDR repo record handles of PDRs we want the host
261 // to pull up.
262 std::vector<uint8_t> eventDataOps{PLDM_RECORDS_ADDED};
263 std::vector<uint8_t> numsOfChangeEntries(1);
264 std::vector<std::vector<ChangeEntry>> changeEntries(
265 numsOfChangeEntries.size());
266 for (auto pdrType : pdrTypes)
267 {
268 const pldm_pdr_record* record{};
269 do
270 {
271 record = pldm_pdr_find_record_by_type(repo, pdrType, record,
272 nullptr, nullptr);
273 if (record && pldm_pdr_record_is_remote(record))
274 {
275 changeEntries[0].push_back(
276 pldm_pdr_get_record_handle(repo, record));
277 }
278 } while (record);
279 }
280 if (changeEntries.empty())
281 {
282 return;
283 }
284 numsOfChangeEntries[0] = changeEntries[0].size();
285
286 // Encode PLDM platform event msg to indicate a PDR repo change.
287 size_t maxSize = PLDM_PDR_REPOSITORY_CHG_EVENT_MIN_LENGTH +
288 PLDM_PDR_REPOSITORY_CHANGE_RECORD_MIN_LENGTH +
289 changeEntries[0].size() * sizeof(uint32_t);
290 std::vector<uint8_t> eventDataVec{};
291 eventDataVec.resize(maxSize);
292 auto eventData =
293 reinterpret_cast<struct pldm_pdr_repository_chg_event_data*>(
294 eventDataVec.data());
295 size_t actualSize{};
296 auto firstEntry = changeEntries[0].data();
297 auto rc = encode_pldm_pdr_repository_chg_event_data(
298 eventDataFormat, 1, eventDataOps.data(), numsOfChangeEntries.data(),
299 &firstEntry, eventData, &actualSize, maxSize);
300 if (rc != PLDM_SUCCESS)
301 {
302 std::cerr
303 << "Failed to encode_pldm_pdr_repository_chg_event_data, rc = "
304 << rc << std::endl;
305 return;
306 }
307 auto instanceId = requester.getInstanceId(mctp_eid);
308 std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) +
309 PLDM_PLATFORM_EVENT_MESSAGE_MIN_REQ_BYTES +
310 actualSize);
311 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
312 rc = encode_platform_event_message_req(
313 instanceId, 1, 0, PLDM_PDR_REPOSITORY_CHG_EVENT, eventDataVec.data(),
Christian Geddes3bdb3c22020-05-01 14:55:39 -0500314 actualSize, request,
315 actualSize + PLDM_PLATFORM_EVENT_MESSAGE_MIN_REQ_BYTES);
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500316 if (rc != PLDM_SUCCESS)
317 {
318 requester.markFree(mctp_eid, instanceId);
319 std::cerr << "Failed to encode_platform_event_message_req, rc = " << rc
320 << std::endl;
321 return;
322 }
323
Tom Joseph74f27c72021-05-16 07:58:53 -0700324 auto platformEventMessageResponseHandler = [](mctp_eid_t /*eid*/,
325 const pldm_msg* response,
326 size_t respMsgLen) {
327 if (response == nullptr || !respMsgLen)
328 {
329 std::cerr << "Failed to receive response for the PDR repository "
330 "changed event"
331 << "\n";
332 return;
333 }
334
335 uint8_t completionCode{};
336 uint8_t status{};
337 auto responsePtr = reinterpret_cast<const struct pldm_msg*>(response);
Pavithra Barithaya54b5a562021-09-27 06:07:10 -0500338 auto rc = decode_platform_event_message_resp(responsePtr, respMsgLen,
339 &completionCode, &status);
Sampa Misrac0c79482021-06-02 08:01:54 -0500340 if (rc || completionCode)
Tom Joseph74f27c72021-05-16 07:58:53 -0700341 {
342 std::cerr << "Failed to decode_platform_event_message_resp: "
343 << "rc=" << rc
344 << ", cc=" << static_cast<unsigned>(completionCode)
345 << std::endl;
346 }
347 };
348
Sampa Misrac0c79482021-06-02 08:01:54 -0500349 rc = handler->registerRequest(
Sampa Misra626c5652021-08-11 10:28:48 -0500350 mctp_eid, instanceId, PLDM_PLATFORM, PLDM_PLATFORM_EVENT_MESSAGE,
Tom Joseph74f27c72021-05-16 07:58:53 -0700351 std::move(requestMsg), std::move(platformEventMessageResponseHandler));
Sampa Misrac0c79482021-06-02 08:01:54 -0500352 if (rc)
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500353 {
Tom Joseph74f27c72021-05-16 07:58:53 -0700354 std::cerr << "Failed to send the PDR repository changed event request"
355 << "\n";
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500356 }
357}
358
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530359void HostPDRHandler::parseStateSensorPDRs(const PDRList& stateSensorPDRs)
Sampa Misra868c8792020-05-26 03:12:13 -0500360{
361 for (const auto& pdr : stateSensorPDRs)
362 {
363 SensorEntry sensorEntry{};
364 const auto& [terminusHandle, sensorID, sensorInfo] =
365 responder::pdr_utils::parseStateSensorPDR(pdr);
366 sensorEntry.sensorID = sensorID;
367 try
368 {
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530369 sensorEntry.terminusID = std::get<0>(tlPDRInfo.at(terminusHandle));
Sampa Misra868c8792020-05-26 03:12:13 -0500370 }
371 // If there is no mapping for terminusHandle assign the reserved TID
372 // value of 0xFF to indicate that.
373 catch (const std::out_of_range& e)
374 {
375 sensorEntry.terminusID = PLDM_TID_RESERVED;
376 }
377 sensorMap.emplace(sensorEntry, std::move(sensorInfo));
378 }
379}
380
Sampa Misrac0c79482021-06-02 08:01:54 -0500381void HostPDRHandler::processHostPDRs(mctp_eid_t /*eid*/,
382 const pldm_msg* response,
383 size_t respMsgLen)
384{
385 static bool merged = false;
386 static PDRList stateSensorPDRs{};
Sampa Misrac0c79482021-06-02 08:01:54 -0500387 uint32_t nextRecordHandle{};
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600388 uint8_t tlEid = 0;
389 bool tlValid = true;
390 uint32_t rh = 0;
391 uint16_t terminusHandle = 0;
Manojkiran Eda3ca40452021-10-04 22:51:37 +0530392 uint16_t pdrTerminusHandle = 0;
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600393 uint8_t tid = 0;
394
Sampa Misrac0c79482021-06-02 08:01:54 -0500395 uint8_t completionCode{};
396 uint32_t nextDataTransferHandle{};
397 uint8_t transferFlag{};
398 uint16_t respCount{};
399 uint8_t transferCRC{};
400 if (response == nullptr || !respMsgLen)
401 {
402 std::cerr << "Failed to receive response for the GetPDR"
403 " command \n";
404 return;
405 }
406
407 auto rc = decode_get_pdr_resp(
408 response, respMsgLen /*- sizeof(pldm_msg_hdr)*/, &completionCode,
409 &nextRecordHandle, &nextDataTransferHandle, &transferFlag, &respCount,
410 nullptr, 0, &transferCRC);
411 std::vector<uint8_t> responsePDRMsg;
412 responsePDRMsg.resize(respMsgLen + sizeof(pldm_msg_hdr));
413 memcpy(responsePDRMsg.data(), response, respMsgLen + sizeof(pldm_msg_hdr));
Sampa Misrac0c79482021-06-02 08:01:54 -0500414 if (rc != PLDM_SUCCESS)
415 {
416 std::cerr << "Failed to decode_get_pdr_resp, rc = " << rc << std::endl;
417 return;
418 }
419 else
420 {
421 std::vector<uint8_t> pdr(respCount, 0);
422 rc = decode_get_pdr_resp(response, respMsgLen, &completionCode,
423 &nextRecordHandle, &nextDataTransferHandle,
424 &transferFlag, &respCount, pdr.data(),
425 respCount, &transferCRC);
426 if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS)
427 {
428 std::cerr << "Failed to decode_get_pdr_resp: "
429 << "rc=" << rc
430 << ", cc=" << static_cast<unsigned>(completionCode)
431 << std::endl;
432 return;
433 }
434 else
435 {
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600436 // when nextRecordHandle is 0, we need the recordHandle of the last
437 // PDR and not 0-1.
438 if (!nextRecordHandle)
439 {
440 rh = nextRecordHandle;
441 }
442 else
443 {
444 rh = nextRecordHandle - 1;
445 }
446
Sampa Misrac0c79482021-06-02 08:01:54 -0500447 auto pdrHdr = reinterpret_cast<pldm_pdr_hdr*>(pdr.data());
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600448 if (!rh)
449 {
450 rh = pdrHdr->record_handle;
451 }
452
Sampa Misrac0c79482021-06-02 08:01:54 -0500453 if (pdrHdr->type == PLDM_PDR_ENTITY_ASSOCIATION)
454 {
455 this->mergeEntityAssociations(pdr);
456 merged = true;
457 }
458 else
459 {
460 if (pdrHdr->type == PLDM_TERMINUS_LOCATOR_PDR)
461 {
Manojkiran Eda3ca40452021-10-04 22:51:37 +0530462 pdrTerminusHandle =
463 extractTerminusHandle<pldm_terminus_locator_pdr>(pdr);
Sampa Misrac0c79482021-06-02 08:01:54 -0500464 auto tlpdr =
465 reinterpret_cast<const pldm_terminus_locator_pdr*>(
466 pdr.data());
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600467
468 terminusHandle = tlpdr->terminus_handle;
469 tid = tlpdr->tid;
470 auto terminus_locator_type = tlpdr->terminus_locator_type;
471 if (terminus_locator_type ==
472 PLDM_TERMINUS_LOCATOR_TYPE_MCTP_EID)
473 {
474 auto locatorValue = reinterpret_cast<
475 const pldm_terminus_locator_type_mctp_eid*>(
476 tlpdr->terminus_locator_value);
477 tlEid = static_cast<uint8_t>(locatorValue->eid);
478 }
479 if (tlpdr->validity == 0)
480 {
481 tlValid = false;
482 }
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530483 tlPDRInfo.insert_or_assign(
484 tlpdr->terminus_handle,
485 std::make_tuple(tlpdr->tid, tlEid, tlpdr->validity));
Sampa Misrac0c79482021-06-02 08:01:54 -0500486 }
487 else if (pdrHdr->type == PLDM_STATE_SENSOR_PDR)
488 {
Manojkiran Eda3ca40452021-10-04 22:51:37 +0530489 pdrTerminusHandle =
490 extractTerminusHandle<pldm_state_sensor_pdr>(pdr);
Sampa Misrac0c79482021-06-02 08:01:54 -0500491 stateSensorPDRs.emplace_back(pdr);
492 }
Manojkiran Eda3ca40452021-10-04 22:51:37 +0530493 else if (pdrHdr->type == PLDM_PDR_FRU_RECORD_SET)
494 {
495 pdrTerminusHandle =
496 extractTerminusHandle<pldm_pdr_fru_record_set>(pdr);
497 }
498 else if (pdrHdr->type == PLDM_STATE_EFFECTER_PDR)
499 {
500 pdrTerminusHandle =
501 extractTerminusHandle<pldm_state_effecter_pdr>(pdr);
502 }
503 else if (pdrHdr->type == PLDM_NUMERIC_EFFECTER_PDR)
504 {
505 pdrTerminusHandle =
506 extractTerminusHandle<pldm_numeric_effecter_value_pdr>(
507 pdr);
508 }
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600509 // if the TLPDR is invalid update the repo accordingly
510 if (!tlValid)
511 {
512 pldm_pdr_update_TL_pdr(repo, terminusHandle, tid, tlEid,
513 tlValid);
514 }
515 else
516 {
Manojkiran Eda3ca40452021-10-04 22:51:37 +0530517 pldm_pdr_add(repo, pdr.data(), respCount, rh, true,
518 pdrTerminusHandle);
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600519 }
Sampa Misrac0c79482021-06-02 08:01:54 -0500520 }
521 }
522 }
523 if (!nextRecordHandle)
524 {
525 /*received last record*/
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530526 this->parseStateSensorPDRs(stateSensorPDRs);
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600527 if (isHostUp())
528 {
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530529 this->setHostSensorState(stateSensorPDRs);
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600530 }
Sampa Misrac0c79482021-06-02 08:01:54 -0500531 stateSensorPDRs.clear();
Sampa Misrac0c79482021-06-02 08:01:54 -0500532 if (merged)
533 {
534 merged = false;
535 deferredPDRRepoChgEvent =
536 std::make_unique<sdeventplus::source::Defer>(
537 event,
538 std::bind(
539 std::mem_fn((&HostPDRHandler::_processPDRRepoChgEvent)),
540 this, std::placeholders::_1));
541 }
542 }
543 else
544 {
545 deferredFetchPDREvent = std::make_unique<sdeventplus::source::Defer>(
546 event,
547 std::bind(std::mem_fn((&HostPDRHandler::_processFetchPDREvent)),
548 this, nextRecordHandle, std::placeholders::_1));
549 }
550}
551
552void HostPDRHandler::_processPDRRepoChgEvent(
553 sdeventplus::source::EventBase& /*source */)
554{
555 deferredPDRRepoChgEvent.reset();
556 this->sendPDRRepositoryChgEvent(
557 std::move(std::vector<uint8_t>(1, PLDM_PDR_ENTITY_ASSOCIATION)),
558 FORMAT_IS_PDR_HANDLES);
559}
560
561void HostPDRHandler::_processFetchPDREvent(
562 uint32_t nextRecordHandle, sdeventplus::source::EventBase& /*source */)
563{
564 deferredFetchPDREvent.reset();
565 if (!this->pdrRecordHandles.empty())
566 {
567 nextRecordHandle = this->pdrRecordHandles.front();
568 this->pdrRecordHandles.pop_front();
569 }
570 this->getHostPDR(nextRecordHandle);
571}
572
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500573void HostPDRHandler::setHostFirmwareCondition()
sampmisr6decfc12021-03-02 11:07:36 +0530574{
sampmisr6decfc12021-03-02 11:07:36 +0530575 responseReceived = false;
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500576 auto instanceId = requester.getInstanceId(mctp_eid);
577 std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) +
578 PLDM_GET_VERSION_REQ_BYTES);
579 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
580 auto rc = encode_get_version_req(instanceId, 0, PLDM_GET_FIRSTPART,
581 PLDM_BASE, request);
582 if (rc != PLDM_SUCCESS)
sampmisr6decfc12021-03-02 11:07:36 +0530583 {
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500584 std::cerr << "GetPLDMVersion encode failure. PLDM error code = "
585 << std::hex << std::showbase << rc << "\n";
586 requester.markFree(mctp_eid, instanceId);
sampmisr6decfc12021-03-02 11:07:36 +0530587 return;
588 }
589
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500590 auto getPLDMVersionHandler = [this](mctp_eid_t /*eid*/,
591 const pldm_msg* response,
592 size_t respMsgLen) {
593 if (response == nullptr || !respMsgLen)
sampmisr6decfc12021-03-02 11:07:36 +0530594 {
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500595 std::cerr << "Failed to receive response for "
596 << "getPLDMVersion command, Host seems to be off \n";
sampmisr6decfc12021-03-02 11:07:36 +0530597 return;
598 }
sampmisr6decfc12021-03-02 11:07:36 +0530599 std::cout << "Getting the response. PLDM RC = " << std::hex
600 << std::showbase
601 << static_cast<uint16_t>(response->payload[0]) << "\n";
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500602 this->responseReceived = true;
603 getHostPDR();
sampmisr6decfc12021-03-02 11:07:36 +0530604 };
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500605 rc = handler->registerRequest(mctp_eid, instanceId, PLDM_BASE,
606 PLDM_GET_PLDM_VERSION, std::move(requestMsg),
607 std::move(getPLDMVersionHandler));
608 if (rc)
sampmisr6decfc12021-03-02 11:07:36 +0530609 {
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500610 std::cerr << "Failed to discover Host state. Assuming Host as off \n";
sampmisr6decfc12021-03-02 11:07:36 +0530611 }
612}
613
614bool HostPDRHandler::isHostUp()
615{
616 return responseReceived;
617}
618
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530619void HostPDRHandler::setHostSensorState(const PDRList& stateSensorPDRs)
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600620{
621 for (const auto& stateSensorPDR : stateSensorPDRs)
622 {
623 auto pdr = reinterpret_cast<const pldm_state_sensor_pdr*>(
624 stateSensorPDR.data());
625
626 if (!pdr)
627 {
628 std::cerr << "Failed to get State sensor PDR" << std::endl;
629 pldm::utils::reportError(
630 "xyz.openbmc_project.bmc.pldm.InternalFailure");
631 return;
632 }
633
634 uint16_t sensorId = pdr->sensor_id;
635
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530636 for (const auto& [terminusHandle, terminusInfo] : tlPDRInfo)
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600637 {
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530638 if (terminusHandle == pdr->terminus_handle)
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600639 {
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530640 if (std::get<2>(terminusInfo) == PLDM_TL_PDR_VALID)
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600641 {
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530642 mctp_eid = std::get<1>(terminusInfo);
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600643 }
644
645 bitfield8_t sensorRearm;
646 sensorRearm.byte = 0;
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530647 uint8_t tid = std::get<0>(terminusInfo);
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600648
649 auto instanceId = requester.getInstanceId(mctp_eid);
650 std::vector<uint8_t> requestMsg(
651 sizeof(pldm_msg_hdr) +
652 PLDM_GET_STATE_SENSOR_READINGS_REQ_BYTES);
653 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
654 auto rc = encode_get_state_sensor_readings_req(
655 instanceId, sensorId, sensorRearm, 0, request);
656
657 if (rc != PLDM_SUCCESS)
658 {
659 requester.markFree(mctp_eid, instanceId);
660 std::cerr << "Failed to "
661 "encode_get_state_sensor_readings_req, rc = "
662 << rc << std::endl;
663 pldm::utils::reportError(
664 "xyz.openbmc_project.bmc.pldm.InternalFailure");
665 return;
666 }
667
668 auto getStateSensorReadingRespHandler = [=, this](
669 mctp_eid_t /*eid*/,
670 const pldm_msg*
671 response,
672 size_t respMsgLen) {
673 if (response == nullptr || !respMsgLen)
674 {
675 std::cerr << "Failed to receive response for "
676 "getStateSensorReading command \n";
677 return;
678 }
679 std::array<get_sensor_state_field, 8> stateField{};
680 uint8_t completionCode = 0;
681 uint8_t comp_sensor_count = 0;
682
683 auto rc = decode_get_state_sensor_readings_resp(
684 response, respMsgLen, &completionCode,
685 &comp_sensor_count, stateField.data());
686
687 if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS)
688 {
689 std::cerr
690 << "Failed to "
691 "decode_get_state_sensor_readings_resp, rc = "
692 << rc
693 << " cc=" << static_cast<unsigned>(completionCode)
694 << std::endl;
695 pldm::utils::reportError(
696 "xyz.openbmc_project.bmc.pldm.InternalFailure");
697 }
698
699 uint8_t eventState;
700 uint8_t previousEventState;
701 uint8_t sensorOffset = comp_sensor_count - 1;
702
703 for (size_t i = 0; i < comp_sensor_count; i++)
704 {
705 eventState = stateField[i].present_state;
706 previousEventState = stateField[i].previous_state;
707
708 emitStateSensorEventSignal(tid, sensorId, sensorOffset,
709 eventState,
710 previousEventState);
711
712 SensorEntry sensorEntry{tid, sensorId};
713
714 pldm::pdr::EntityInfo entityInfo{};
715 pldm::pdr::CompositeSensorStates
716 compositeSensorStates{};
717
718 try
719 {
720 std::tie(entityInfo, compositeSensorStates) =
721 lookupSensorInfo(sensorEntry);
722 }
723 catch (const std::out_of_range& e)
724 {
725 try
726 {
727 sensorEntry.terminusID = PLDM_TID_RESERVED;
728 std::tie(entityInfo, compositeSensorStates) =
729 lookupSensorInfo(sensorEntry);
730 }
731 catch (const std::out_of_range& e)
732 {
733 std::cerr << "No mapping for the events"
734 << std::endl;
735 }
736 }
737
738 if (sensorOffset > compositeSensorStates.size())
739 {
740 std::cerr
741 << " Error Invalid data, Invalid sensor offset"
742 << std::endl;
743 return;
744 }
745
746 const auto& possibleStates =
747 compositeSensorStates[sensorOffset];
748 if (possibleStates.find(eventState) ==
749 possibleStates.end())
750 {
751 std::cerr
752 << " Error invalid_data, Invalid event state"
753 << std::endl;
754 return;
755 }
756 const auto& [containerId, entityType, entityInstance] =
757 entityInfo;
758 pldm::responder::events::StateSensorEntry
759 stateSensorEntry{containerId, entityType,
760 entityInstance, sensorOffset};
761 handleStateSensorEvent(stateSensorEntry, eventState);
762 }
763 };
764
765 rc = handler->registerRequest(
766 mctp_eid, instanceId, PLDM_PLATFORM,
767 PLDM_GET_STATE_SENSOR_READINGS, std::move(requestMsg),
768 std::move(getStateSensorReadingRespHandler));
769
770 if (rc != PLDM_SUCCESS)
771 {
772 std::cerr << " Failed to send request to get State sensor "
773 "reading on Host "
774 << std::endl;
775 }
776 }
777 }
778 }
779}
Pavithra Barithaya51efaf82020-04-02 02:42:27 -0500780} // namespace pldm