blob: 922e9db2b490a28250afbaa2818810a649c1fd1f [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
Pavithra Barithayae8beb892020-04-14 23:24:25 -05005#include <assert.h>
George Liuc453e162022-12-21 17:16:23 +08006#include <libpldm/pldm.h>
Pavithra Barithayae8beb892020-04-14 23:24:25 -05007
Deepak Kodihalli87514cc2020-04-16 09:08:38 -05008#include <nlohmann/json.hpp>
sampmisr6decfc12021-03-02 11:07:36 +05309#include <sdeventplus/clock.hpp>
10#include <sdeventplus/exception.hpp>
11#include <sdeventplus/source/io.hpp>
12#include <sdeventplus/source/time.hpp>
Deepak Kodihalli87514cc2020-04-16 09:08:38 -050013
George Liu6492f522020-06-16 10:34:05 +080014#include <fstream>
Pavithra Barithaya51efaf82020-04-02 02:42:27 -050015
16namespace pldm
17{
Brad Bishop5079ac42021-08-19 18:35:06 -040018using namespace pldm::dbus_api;
19using namespace pldm::responder::events;
Deepak Kodihalli6b1d1ca2020-04-27 07:24:51 -050020using namespace pldm::utils;
21using namespace sdbusplus::bus::match::rules;
Deepak Kodihalli87514cc2020-04-16 09:08:38 -050022using Json = nlohmann::json;
23namespace fs = std::filesystem;
24constexpr auto fruJson = "host_frus.json";
25const Json emptyJson{};
26const std::vector<Json> emptyJsonList{};
27
Manojkiran Eda3ca40452021-10-04 22:51:37 +053028template <typename T>
29uint16_t extractTerminusHandle(std::vector<uint8_t>& pdr)
30{
31 T* var = nullptr;
32 if (std::is_same<T, pldm_pdr_fru_record_set>::value)
33 {
34 var = (T*)(pdr.data() + sizeof(pldm_pdr_hdr));
35 }
36 else
37 {
38 var = (T*)(pdr.data());
39 }
40 if (var != nullptr)
41 {
42 return var->terminus_handle;
43 }
44 return TERMINUS_HANDLE;
45}
46
Tom Joseph74f27c72021-05-16 07:58:53 -070047HostPDRHandler::HostPDRHandler(
48 int mctp_fd, uint8_t mctp_eid, sdeventplus::Event& event, pldm_pdr* repo,
49 const std::string& eventsJsonsDir, pldm_entity_association_tree* entityTree,
50 pldm_entity_association_tree* bmcEntityTree, Requester& requester,
Tom Josephe5268cd2021-09-07 13:04:03 +053051 pldm::requester::Handler<pldm::requester::Request>* handler) :
Deepak Kodihalli87514cc2020-04-16 09:08:38 -050052 mctp_fd(mctp_fd),
Pavithra Barithaya3aec9972020-12-14 01:55:44 -060053 mctp_eid(mctp_eid), event(event), repo(repo),
54 stateSensorHandler(eventsJsonsDir), entityTree(entityTree),
Tom Josephe5268cd2021-09-07 13:04:03 +053055 bmcEntityTree(bmcEntityTree), requester(requester), handler(handler)
Deepak Kodihalli87514cc2020-04-16 09:08:38 -050056{
57 fs::path hostFruJson(fs::path(HOST_JSONS_DIR) / fruJson);
58 if (fs::exists(hostFruJson))
59 {
Pavithra Barithayae8beb892020-04-14 23:24:25 -050060 // Note parent entities for entities sent down by the host firmware.
61 // This will enable a merge of entity associations.
Deepak Kodihalli87514cc2020-04-16 09:08:38 -050062 try
63 {
64 std::ifstream jsonFile(hostFruJson);
65 auto data = Json::parse(jsonFile, nullptr, false);
66 if (data.is_discarded())
67 {
68 std::cerr << "Parsing Host FRU json file failed" << std::endl;
69 }
70 else
71 {
72 auto entities = data.value("entities", emptyJsonList);
73 for (auto& entity : entities)
74 {
75 EntityType entityType = entity.value("entity_type", 0);
76 auto parent = entity.value("parent", emptyJson);
77 pldm_entity p{};
78 p.entity_type = parent.value("entity_type", 0);
79 p.entity_instance_num = parent.value("entity_instance", 0);
80 parents.emplace(entityType, std::move(p));
81 }
82 }
83 }
84 catch (const std::exception& e)
85 {
86 std::cerr << "Parsing Host FRU json file failed, exception = "
87 << e.what() << std::endl;
88 }
89 }
Deepak Kodihalli6b1d1ca2020-04-27 07:24:51 -050090
Patrick Williams84b790c2022-07-22 19:26:56 -050091 hostOffMatch = std::make_unique<sdbusplus::bus::match_t>(
Deepak Kodihalli6b1d1ca2020-04-27 07:24:51 -050092 pldm::utils::DBusHandler::getBus(),
93 propertiesChanged("/xyz/openbmc_project/state/host0",
94 "xyz.openbmc_project.State.Host"),
Patrick Williams84b790c2022-07-22 19:26:56 -050095 [this, repo, entityTree, bmcEntityTree](sdbusplus::message_t& msg) {
Deepak Kodihalli6b1d1ca2020-04-27 07:24:51 -050096 DbusChangedProps props{};
97 std::string intf;
98 msg.read(intf, props);
99 const auto itr = props.find("CurrentHostState");
100 if (itr != props.end())
101 {
102 PropertyValue value = itr->second;
103 auto propVal = std::get<std::string>(value);
104 if (propVal == "xyz.openbmc_project.State.Host.HostState.Off")
105 {
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530106 // Delete all the remote terminus information
Manojkiran Eda8fee19a2021-11-15 12:07:44 +0530107 std::erase_if(tlPDRInfo, [](const auto& item) {
108 auto const& [key, value] = item;
109 return key != TERMINUS_HANDLE;
110 });
Deepak Kodihalli6b1d1ca2020-04-27 07:24:51 -0500111 pldm_pdr_remove_remote_pdrs(repo);
Sampa Misrac073a202021-05-08 10:56:05 -0500112 pldm_entity_association_tree_destroy_root(entityTree);
113 pldm_entity_association_tree_copy_root(bmcEntityTree,
114 entityTree);
Tom Josephb4268602020-04-17 17:20:45 +0530115 this->sensorMap.clear();
Pavithra Barithaya23025b92021-09-28 05:22:52 -0500116 this->responseReceived = false;
Deepak Kodihalli6b1d1ca2020-04-27 07:24:51 -0500117 }
118 }
119 });
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500120}
121
Deepak Kodihalli7246e0c2020-07-08 06:40:18 -0500122void HostPDRHandler::fetchPDR(PDRRecordHandles&& recordHandles)
Pavithra Barithaya51efaf82020-04-02 02:42:27 -0500123{
Deepak Kodihalli8cb6f662020-04-10 02:55:43 -0500124 pdrRecordHandles.clear();
Pavithra Barithayaae5c97e2022-08-29 02:57:59 -0500125 modifiedPDRRecordHandles.clear();
126
127 if (isHostPdrModified)
128 {
129 modifiedPDRRecordHandles = std::move(recordHandles);
130 }
131 else
132 {
133 pdrRecordHandles = std::move(recordHandles);
134 }
Deepak Kodihalli8cb6f662020-04-10 02:55:43 -0500135
136 // Defer the actual fetch of PDRs from the host (by queuing the call on the
137 // main event loop). That way, we can respond to the platform event msg from
138 // the host firmware.
139 pdrFetchEvent = std::make_unique<sdeventplus::source::Defer>(
140 event, std::bind(std::mem_fn(&HostPDRHandler::_fetchPDR), this,
141 std::placeholders::_1));
142}
143
144void HostPDRHandler::_fetchPDR(sdeventplus::source::EventBase& /*source*/)
145{
Sampa Misrac0c79482021-06-02 08:01:54 -0500146 getHostPDR();
147}
148
149void HostPDRHandler::getHostPDR(uint32_t nextRecordHandle)
150{
Deepak Kodihalli8cb6f662020-04-10 02:55:43 -0500151 pdrFetchEvent.reset();
152
Pavithra Barithaya51efaf82020-04-02 02:42:27 -0500153 std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) +
154 PLDM_GET_PDR_REQ_BYTES);
155 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
Deepak Kodihalli7246e0c2020-07-08 06:40:18 -0500156 uint32_t recordHandle{};
Pavithra Barithayaae5c97e2022-08-29 02:57:59 -0500157 if (!nextRecordHandle && (!modifiedPDRRecordHandles.empty()) &&
158 isHostPdrModified)
Deepak Kodihalli7246e0c2020-07-08 06:40:18 -0500159 {
Pavithra Barithayaae5c97e2022-08-29 02:57:59 -0500160 recordHandle = modifiedPDRRecordHandles.front();
161 modifiedPDRRecordHandles.pop_front();
162 }
163 else if (!nextRecordHandle && (!pdrRecordHandles.empty()))
164 {
165 recordHandle = pdrRecordHandles.front();
166 pdrRecordHandles.pop_front();
Sampa Misrac0c79482021-06-02 08:01:54 -0500167 }
168 else
169 {
170 recordHandle = nextRecordHandle;
171 }
172 auto instanceId = requester.getInstanceId(mctp_eid);
173
174 auto rc =
175 encode_get_pdr_req(instanceId, recordHandle, 0, PLDM_GET_FIRSTPART,
176 UINT16_MAX, 0, request, PLDM_GET_PDR_REQ_BYTES);
177 if (rc != PLDM_SUCCESS)
178 {
179 requester.markFree(mctp_eid, instanceId);
180 std::cerr << "Failed to encode_get_pdr_req, rc = " << rc << std::endl;
181 return;
182 }
Deepak Kodihalli7246e0c2020-07-08 06:40:18 -0500183
Sampa Misrac0c79482021-06-02 08:01:54 -0500184 rc = handler->registerRequest(
185 mctp_eid, instanceId, PLDM_PLATFORM, PLDM_GET_PDR,
186 std::move(requestMsg),
187 std::move(std::bind_front(&HostPDRHandler::processHostPDRs, this)));
188 if (rc)
Pavithra Barithaya51efaf82020-04-02 02:42:27 -0500189 {
Sampa Misrac0c79482021-06-02 08:01:54 -0500190 std::cerr << "Failed to send the GetPDR request to Host \n";
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500191 }
Pavithra Barithaya51efaf82020-04-02 02:42:27 -0500192}
193
Pavithra Barithaya3aec9972020-12-14 01:55:44 -0600194int HostPDRHandler::handleStateSensorEvent(const StateSensorEntry& entry,
195 pdr::EventState state)
196{
197 auto rc = stateSensorHandler.eventAction(entry, state);
198 if (rc != PLDM_SUCCESS)
199 {
200 std::cerr << "Failed to fetch and update D-bus property, rc = " << rc
201 << std::endl;
202 return rc;
203 }
204 return PLDM_SUCCESS;
205}
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500206bool HostPDRHandler::getParent(EntityType type, pldm_entity& parent)
207{
208 auto found = parents.find(type);
209 if (found != parents.end())
210 {
211 parent.entity_type = found->second.entity_type;
212 parent.entity_instance_num = found->second.entity_instance_num;
213 return true;
214 }
215
216 return false;
217}
218
219void HostPDRHandler::mergeEntityAssociations(const std::vector<uint8_t>& pdr)
220{
221 size_t numEntities{};
222 pldm_entity* entities = nullptr;
223 bool merged = false;
224 auto entityPdr = reinterpret_cast<pldm_pdr_entity_association*>(
225 const_cast<uint8_t*>(pdr.data()) + sizeof(pldm_pdr_hdr));
226
227 pldm_entity_association_pdr_extract(pdr.data(), pdr.size(), &numEntities,
228 &entities);
229 for (size_t i = 0; i < numEntities; ++i)
230 {
231 pldm_entity parent{};
232 if (getParent(entities[i].entity_type, parent))
233 {
234 auto node = pldm_entity_association_tree_find(entityTree, &parent);
235 if (node)
236 {
George Liu64a8f0f2021-06-12 10:56:11 +0800237 pldm_entity_association_tree_add(entityTree, &entities[i],
238 0xFFFF, node,
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500239 entityPdr->association_type);
240 merged = true;
241 }
242 }
243 }
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500244
245 if (merged)
246 {
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500247 // Update our PDR repo with the merged entity association PDRs
Sampa Misra719ed392021-06-04 05:15:13 -0500248 pldm_entity_node* node = nullptr;
249 pldm_find_entity_ref_in_tree(entityTree, entities[0], &node);
250 if (node == nullptr)
251 {
252 std::cerr
253 << "\ncould not find referrence of the entity in the tree \n";
254 }
255 else
256 {
Manojkiran Eda3ca40452021-10-04 22:51:37 +0530257 pldm_entity_association_pdr_add_from_node(
258 node, repo, &entities, numEntities, true, TERMINUS_HANDLE);
Sampa Misra719ed392021-06-04 05:15:13 -0500259 }
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500260 }
Sampa Misra719ed392021-06-04 05:15:13 -0500261 free(entities);
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500262}
263
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500264void HostPDRHandler::sendPDRRepositoryChgEvent(std::vector<uint8_t>&& pdrTypes,
265 uint8_t eventDataFormat)
266{
267 assert(eventDataFormat == FORMAT_IS_PDR_HANDLES);
268
269 // Extract from the PDR repo record handles of PDRs we want the host
270 // to pull up.
271 std::vector<uint8_t> eventDataOps{PLDM_RECORDS_ADDED};
272 std::vector<uint8_t> numsOfChangeEntries(1);
273 std::vector<std::vector<ChangeEntry>> changeEntries(
274 numsOfChangeEntries.size());
275 for (auto pdrType : pdrTypes)
276 {
277 const pldm_pdr_record* record{};
278 do
279 {
280 record = pldm_pdr_find_record_by_type(repo, pdrType, record,
281 nullptr, nullptr);
282 if (record && pldm_pdr_record_is_remote(record))
283 {
284 changeEntries[0].push_back(
285 pldm_pdr_get_record_handle(repo, record));
286 }
287 } while (record);
288 }
289 if (changeEntries.empty())
290 {
291 return;
292 }
293 numsOfChangeEntries[0] = changeEntries[0].size();
294
295 // Encode PLDM platform event msg to indicate a PDR repo change.
296 size_t maxSize = PLDM_PDR_REPOSITORY_CHG_EVENT_MIN_LENGTH +
297 PLDM_PDR_REPOSITORY_CHANGE_RECORD_MIN_LENGTH +
298 changeEntries[0].size() * sizeof(uint32_t);
299 std::vector<uint8_t> eventDataVec{};
300 eventDataVec.resize(maxSize);
301 auto eventData =
302 reinterpret_cast<struct pldm_pdr_repository_chg_event_data*>(
303 eventDataVec.data());
304 size_t actualSize{};
305 auto firstEntry = changeEntries[0].data();
306 auto rc = encode_pldm_pdr_repository_chg_event_data(
307 eventDataFormat, 1, eventDataOps.data(), numsOfChangeEntries.data(),
308 &firstEntry, eventData, &actualSize, maxSize);
309 if (rc != PLDM_SUCCESS)
310 {
311 std::cerr
312 << "Failed to encode_pldm_pdr_repository_chg_event_data, rc = "
313 << rc << std::endl;
314 return;
315 }
316 auto instanceId = requester.getInstanceId(mctp_eid);
317 std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) +
318 PLDM_PLATFORM_EVENT_MESSAGE_MIN_REQ_BYTES +
319 actualSize);
320 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
321 rc = encode_platform_event_message_req(
322 instanceId, 1, 0, PLDM_PDR_REPOSITORY_CHG_EVENT, eventDataVec.data(),
Christian Geddes3bdb3c22020-05-01 14:55:39 -0500323 actualSize, request,
324 actualSize + PLDM_PLATFORM_EVENT_MESSAGE_MIN_REQ_BYTES);
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500325 if (rc != PLDM_SUCCESS)
326 {
327 requester.markFree(mctp_eid, instanceId);
328 std::cerr << "Failed to encode_platform_event_message_req, rc = " << rc
329 << std::endl;
330 return;
331 }
332
Tom Joseph74f27c72021-05-16 07:58:53 -0700333 auto platformEventMessageResponseHandler = [](mctp_eid_t /*eid*/,
334 const pldm_msg* response,
335 size_t respMsgLen) {
336 if (response == nullptr || !respMsgLen)
337 {
338 std::cerr << "Failed to receive response for the PDR repository "
339 "changed event"
340 << "\n";
341 return;
342 }
343
344 uint8_t completionCode{};
345 uint8_t status{};
346 auto responsePtr = reinterpret_cast<const struct pldm_msg*>(response);
Pavithra Barithaya54b5a562021-09-27 06:07:10 -0500347 auto rc = decode_platform_event_message_resp(responsePtr, respMsgLen,
348 &completionCode, &status);
Sampa Misrac0c79482021-06-02 08:01:54 -0500349 if (rc || completionCode)
Tom Joseph74f27c72021-05-16 07:58:53 -0700350 {
351 std::cerr << "Failed to decode_platform_event_message_resp: "
352 << "rc=" << rc
353 << ", cc=" << static_cast<unsigned>(completionCode)
354 << std::endl;
355 }
356 };
357
Sampa Misrac0c79482021-06-02 08:01:54 -0500358 rc = handler->registerRequest(
Sampa Misra626c5652021-08-11 10:28:48 -0500359 mctp_eid, instanceId, PLDM_PLATFORM, PLDM_PLATFORM_EVENT_MESSAGE,
Tom Joseph74f27c72021-05-16 07:58:53 -0700360 std::move(requestMsg), std::move(platformEventMessageResponseHandler));
Sampa Misrac0c79482021-06-02 08:01:54 -0500361 if (rc)
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500362 {
Tom Joseph74f27c72021-05-16 07:58:53 -0700363 std::cerr << "Failed to send the PDR repository changed event request"
364 << "\n";
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500365 }
366}
367
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530368void HostPDRHandler::parseStateSensorPDRs(const PDRList& stateSensorPDRs)
Sampa Misra868c8792020-05-26 03:12:13 -0500369{
370 for (const auto& pdr : stateSensorPDRs)
371 {
372 SensorEntry sensorEntry{};
373 const auto& [terminusHandle, sensorID, sensorInfo] =
374 responder::pdr_utils::parseStateSensorPDR(pdr);
375 sensorEntry.sensorID = sensorID;
376 try
377 {
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530378 sensorEntry.terminusID = std::get<0>(tlPDRInfo.at(terminusHandle));
Sampa Misra868c8792020-05-26 03:12:13 -0500379 }
380 // If there is no mapping for terminusHandle assign the reserved TID
381 // value of 0xFF to indicate that.
382 catch (const std::out_of_range& e)
383 {
384 sensorEntry.terminusID = PLDM_TID_RESERVED;
385 }
386 sensorMap.emplace(sensorEntry, std::move(sensorInfo));
387 }
388}
389
Sampa Misrac0c79482021-06-02 08:01:54 -0500390void HostPDRHandler::processHostPDRs(mctp_eid_t /*eid*/,
391 const pldm_msg* response,
392 size_t respMsgLen)
393{
394 static bool merged = false;
395 static PDRList stateSensorPDRs{};
Sampa Misrac0c79482021-06-02 08:01:54 -0500396 uint32_t nextRecordHandle{};
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600397 uint8_t tlEid = 0;
398 bool tlValid = true;
399 uint32_t rh = 0;
400 uint16_t terminusHandle = 0;
Manojkiran Eda3ca40452021-10-04 22:51:37 +0530401 uint16_t pdrTerminusHandle = 0;
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600402 uint8_t tid = 0;
403
Sampa Misrac0c79482021-06-02 08:01:54 -0500404 uint8_t completionCode{};
405 uint32_t nextDataTransferHandle{};
406 uint8_t transferFlag{};
407 uint16_t respCount{};
408 uint8_t transferCRC{};
409 if (response == nullptr || !respMsgLen)
410 {
411 std::cerr << "Failed to receive response for the GetPDR"
412 " command \n";
413 return;
414 }
415
416 auto rc = decode_get_pdr_resp(
417 response, respMsgLen /*- sizeof(pldm_msg_hdr)*/, &completionCode,
418 &nextRecordHandle, &nextDataTransferHandle, &transferFlag, &respCount,
419 nullptr, 0, &transferCRC);
420 std::vector<uint8_t> responsePDRMsg;
421 responsePDRMsg.resize(respMsgLen + sizeof(pldm_msg_hdr));
422 memcpy(responsePDRMsg.data(), response, respMsgLen + sizeof(pldm_msg_hdr));
Sampa Misrac0c79482021-06-02 08:01:54 -0500423 if (rc != PLDM_SUCCESS)
424 {
425 std::cerr << "Failed to decode_get_pdr_resp, rc = " << rc << std::endl;
426 return;
427 }
428 else
429 {
430 std::vector<uint8_t> pdr(respCount, 0);
431 rc = decode_get_pdr_resp(response, respMsgLen, &completionCode,
432 &nextRecordHandle, &nextDataTransferHandle,
433 &transferFlag, &respCount, pdr.data(),
434 respCount, &transferCRC);
435 if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS)
436 {
437 std::cerr << "Failed to decode_get_pdr_resp: "
438 << "rc=" << rc
439 << ", cc=" << static_cast<unsigned>(completionCode)
440 << std::endl;
441 return;
442 }
443 else
444 {
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600445 // when nextRecordHandle is 0, we need the recordHandle of the last
446 // PDR and not 0-1.
447 if (!nextRecordHandle)
448 {
449 rh = nextRecordHandle;
450 }
451 else
452 {
453 rh = nextRecordHandle - 1;
454 }
455
Sampa Misrac0c79482021-06-02 08:01:54 -0500456 auto pdrHdr = reinterpret_cast<pldm_pdr_hdr*>(pdr.data());
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600457 if (!rh)
458 {
459 rh = pdrHdr->record_handle;
460 }
461
Sampa Misrac0c79482021-06-02 08:01:54 -0500462 if (pdrHdr->type == PLDM_PDR_ENTITY_ASSOCIATION)
463 {
464 this->mergeEntityAssociations(pdr);
465 merged = true;
466 }
467 else
468 {
469 if (pdrHdr->type == PLDM_TERMINUS_LOCATOR_PDR)
470 {
Manojkiran Eda3ca40452021-10-04 22:51:37 +0530471 pdrTerminusHandle =
472 extractTerminusHandle<pldm_terminus_locator_pdr>(pdr);
Sampa Misrac0c79482021-06-02 08:01:54 -0500473 auto tlpdr =
474 reinterpret_cast<const pldm_terminus_locator_pdr*>(
475 pdr.data());
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600476
477 terminusHandle = tlpdr->terminus_handle;
478 tid = tlpdr->tid;
479 auto terminus_locator_type = tlpdr->terminus_locator_type;
480 if (terminus_locator_type ==
481 PLDM_TERMINUS_LOCATOR_TYPE_MCTP_EID)
482 {
483 auto locatorValue = reinterpret_cast<
484 const pldm_terminus_locator_type_mctp_eid*>(
485 tlpdr->terminus_locator_value);
486 tlEid = static_cast<uint8_t>(locatorValue->eid);
487 }
488 if (tlpdr->validity == 0)
489 {
490 tlValid = false;
491 }
Pavithra Barithaya52aad392022-08-02 04:18:52 -0500492 for (const auto& terminusMap : tlPDRInfo)
493 {
494 if ((terminusHandle == (terminusMap.first)) &&
495 (get<1>(terminusMap.second) == tlEid) &&
496 (get<2>(terminusMap.second) == tlpdr->validity))
497 {
498 // TL PDR already present with same validity don't
499 // add the PDR to the repo just return
500 return;
501 }
502 }
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530503 tlPDRInfo.insert_or_assign(
504 tlpdr->terminus_handle,
505 std::make_tuple(tlpdr->tid, tlEid, tlpdr->validity));
Sampa Misrac0c79482021-06-02 08:01:54 -0500506 }
507 else if (pdrHdr->type == PLDM_STATE_SENSOR_PDR)
508 {
Manojkiran Eda3ca40452021-10-04 22:51:37 +0530509 pdrTerminusHandle =
510 extractTerminusHandle<pldm_state_sensor_pdr>(pdr);
Sampa Misrac0c79482021-06-02 08:01:54 -0500511 stateSensorPDRs.emplace_back(pdr);
512 }
Manojkiran Eda3ca40452021-10-04 22:51:37 +0530513 else if (pdrHdr->type == PLDM_PDR_FRU_RECORD_SET)
514 {
515 pdrTerminusHandle =
516 extractTerminusHandle<pldm_pdr_fru_record_set>(pdr);
517 }
518 else if (pdrHdr->type == PLDM_STATE_EFFECTER_PDR)
519 {
520 pdrTerminusHandle =
521 extractTerminusHandle<pldm_state_effecter_pdr>(pdr);
522 }
523 else if (pdrHdr->type == PLDM_NUMERIC_EFFECTER_PDR)
524 {
525 pdrTerminusHandle =
526 extractTerminusHandle<pldm_numeric_effecter_value_pdr>(
527 pdr);
528 }
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600529 // if the TLPDR is invalid update the repo accordingly
530 if (!tlValid)
531 {
532 pldm_pdr_update_TL_pdr(repo, terminusHandle, tid, tlEid,
533 tlValid);
534 }
535 else
536 {
Manojkiran Eda3ca40452021-10-04 22:51:37 +0530537 pldm_pdr_add(repo, pdr.data(), respCount, rh, true,
538 pdrTerminusHandle);
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600539 }
Sampa Misrac0c79482021-06-02 08:01:54 -0500540 }
541 }
542 }
543 if (!nextRecordHandle)
544 {
545 /*received last record*/
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530546 this->parseStateSensorPDRs(stateSensorPDRs);
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600547 if (isHostUp())
548 {
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530549 this->setHostSensorState(stateSensorPDRs);
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600550 }
Sampa Misrac0c79482021-06-02 08:01:54 -0500551 stateSensorPDRs.clear();
Sampa Misrac0c79482021-06-02 08:01:54 -0500552 if (merged)
553 {
554 merged = false;
555 deferredPDRRepoChgEvent =
556 std::make_unique<sdeventplus::source::Defer>(
557 event,
558 std::bind(
559 std::mem_fn((&HostPDRHandler::_processPDRRepoChgEvent)),
560 this, std::placeholders::_1));
561 }
562 }
563 else
564 {
Pavithra Barithayaae5c97e2022-08-29 02:57:59 -0500565 if (modifiedPDRRecordHandles.empty() && isHostPdrModified)
566 {
567 isHostPdrModified = false;
568 }
569 else
570 {
571 deferredFetchPDREvent =
572 std::make_unique<sdeventplus::source::Defer>(
573 event,
574 std::bind(
575 std::mem_fn((&HostPDRHandler::_processFetchPDREvent)),
576 this, nextRecordHandle, std::placeholders::_1));
577 }
Sampa Misrac0c79482021-06-02 08:01:54 -0500578 }
579}
580
581void HostPDRHandler::_processPDRRepoChgEvent(
582 sdeventplus::source::EventBase& /*source */)
583{
584 deferredPDRRepoChgEvent.reset();
585 this->sendPDRRepositoryChgEvent(
586 std::move(std::vector<uint8_t>(1, PLDM_PDR_ENTITY_ASSOCIATION)),
587 FORMAT_IS_PDR_HANDLES);
588}
589
590void HostPDRHandler::_processFetchPDREvent(
591 uint32_t nextRecordHandle, sdeventplus::source::EventBase& /*source */)
592{
593 deferredFetchPDREvent.reset();
594 if (!this->pdrRecordHandles.empty())
595 {
596 nextRecordHandle = this->pdrRecordHandles.front();
597 this->pdrRecordHandles.pop_front();
598 }
Pavithra Barithayaae5c97e2022-08-29 02:57:59 -0500599 if (isHostPdrModified && (!this->modifiedPDRRecordHandles.empty()))
600 {
601 nextRecordHandle = this->modifiedPDRRecordHandles.front();
602 this->modifiedPDRRecordHandles.pop_front();
603 }
Sampa Misrac0c79482021-06-02 08:01:54 -0500604 this->getHostPDR(nextRecordHandle);
605}
606
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500607void HostPDRHandler::setHostFirmwareCondition()
sampmisr6decfc12021-03-02 11:07:36 +0530608{
sampmisr6decfc12021-03-02 11:07:36 +0530609 responseReceived = false;
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500610 auto instanceId = requester.getInstanceId(mctp_eid);
611 std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) +
612 PLDM_GET_VERSION_REQ_BYTES);
613 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
614 auto rc = encode_get_version_req(instanceId, 0, PLDM_GET_FIRSTPART,
615 PLDM_BASE, request);
616 if (rc != PLDM_SUCCESS)
sampmisr6decfc12021-03-02 11:07:36 +0530617 {
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500618 std::cerr << "GetPLDMVersion encode failure. PLDM error code = "
619 << std::hex << std::showbase << rc << "\n";
620 requester.markFree(mctp_eid, instanceId);
sampmisr6decfc12021-03-02 11:07:36 +0530621 return;
622 }
623
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500624 auto getPLDMVersionHandler = [this](mctp_eid_t /*eid*/,
625 const pldm_msg* response,
626 size_t respMsgLen) {
627 if (response == nullptr || !respMsgLen)
sampmisr6decfc12021-03-02 11:07:36 +0530628 {
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500629 std::cerr << "Failed to receive response for "
630 << "getPLDMVersion command, Host seems to be off \n";
sampmisr6decfc12021-03-02 11:07:36 +0530631 return;
632 }
sampmisr6decfc12021-03-02 11:07:36 +0530633 std::cout << "Getting the response. PLDM RC = " << std::hex
634 << std::showbase
635 << static_cast<uint16_t>(response->payload[0]) << "\n";
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500636 this->responseReceived = true;
637 getHostPDR();
sampmisr6decfc12021-03-02 11:07:36 +0530638 };
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500639 rc = handler->registerRequest(mctp_eid, instanceId, PLDM_BASE,
640 PLDM_GET_PLDM_VERSION, std::move(requestMsg),
641 std::move(getPLDMVersionHandler));
642 if (rc)
sampmisr6decfc12021-03-02 11:07:36 +0530643 {
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500644 std::cerr << "Failed to discover Host state. Assuming Host as off \n";
sampmisr6decfc12021-03-02 11:07:36 +0530645 }
646}
647
648bool HostPDRHandler::isHostUp()
649{
650 return responseReceived;
651}
652
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530653void HostPDRHandler::setHostSensorState(const PDRList& stateSensorPDRs)
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600654{
655 for (const auto& stateSensorPDR : stateSensorPDRs)
656 {
657 auto pdr = reinterpret_cast<const pldm_state_sensor_pdr*>(
658 stateSensorPDR.data());
659
660 if (!pdr)
661 {
662 std::cerr << "Failed to get State sensor PDR" << std::endl;
663 pldm::utils::reportError(
664 "xyz.openbmc_project.bmc.pldm.InternalFailure");
665 return;
666 }
667
668 uint16_t sensorId = pdr->sensor_id;
669
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530670 for (const auto& [terminusHandle, terminusInfo] : tlPDRInfo)
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600671 {
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530672 if (terminusHandle == pdr->terminus_handle)
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600673 {
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530674 if (std::get<2>(terminusInfo) == PLDM_TL_PDR_VALID)
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600675 {
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530676 mctp_eid = std::get<1>(terminusInfo);
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600677 }
678
679 bitfield8_t sensorRearm;
680 sensorRearm.byte = 0;
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530681 uint8_t tid = std::get<0>(terminusInfo);
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600682
683 auto instanceId = requester.getInstanceId(mctp_eid);
684 std::vector<uint8_t> requestMsg(
685 sizeof(pldm_msg_hdr) +
686 PLDM_GET_STATE_SENSOR_READINGS_REQ_BYTES);
687 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
688 auto rc = encode_get_state_sensor_readings_req(
689 instanceId, sensorId, sensorRearm, 0, request);
690
691 if (rc != PLDM_SUCCESS)
692 {
693 requester.markFree(mctp_eid, instanceId);
694 std::cerr << "Failed to "
695 "encode_get_state_sensor_readings_req, rc = "
696 << rc << std::endl;
697 pldm::utils::reportError(
698 "xyz.openbmc_project.bmc.pldm.InternalFailure");
699 return;
700 }
701
702 auto getStateSensorReadingRespHandler = [=, this](
703 mctp_eid_t /*eid*/,
704 const pldm_msg*
705 response,
706 size_t respMsgLen) {
707 if (response == nullptr || !respMsgLen)
708 {
709 std::cerr << "Failed to receive response for "
710 "getStateSensorReading command \n";
711 return;
712 }
713 std::array<get_sensor_state_field, 8> stateField{};
714 uint8_t completionCode = 0;
715 uint8_t comp_sensor_count = 0;
716
717 auto rc = decode_get_state_sensor_readings_resp(
718 response, respMsgLen, &completionCode,
719 &comp_sensor_count, stateField.data());
720
721 if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS)
722 {
723 std::cerr
724 << "Failed to "
725 "decode_get_state_sensor_readings_resp, rc = "
726 << rc
727 << " cc=" << static_cast<unsigned>(completionCode)
728 << std::endl;
729 pldm::utils::reportError(
730 "xyz.openbmc_project.bmc.pldm.InternalFailure");
731 }
732
733 uint8_t eventState;
734 uint8_t previousEventState;
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600735
RIYA DIXITbb5fda42022-09-27 06:48:08 -0500736 for (uint8_t sensorOffset = 0;
737 sensorOffset < comp_sensor_count; sensorOffset++)
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600738 {
RIYA DIXITbb5fda42022-09-27 06:48:08 -0500739 eventState = stateField[sensorOffset].present_state;
740 previousEventState =
741 stateField[sensorOffset].previous_state;
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600742
743 emitStateSensorEventSignal(tid, sensorId, sensorOffset,
744 eventState,
745 previousEventState);
746
747 SensorEntry sensorEntry{tid, sensorId};
748
749 pldm::pdr::EntityInfo entityInfo{};
750 pldm::pdr::CompositeSensorStates
751 compositeSensorStates{};
752
753 try
754 {
755 std::tie(entityInfo, compositeSensorStates) =
756 lookupSensorInfo(sensorEntry);
757 }
758 catch (const std::out_of_range& e)
759 {
760 try
761 {
762 sensorEntry.terminusID = PLDM_TID_RESERVED;
763 std::tie(entityInfo, compositeSensorStates) =
764 lookupSensorInfo(sensorEntry);
765 }
766 catch (const std::out_of_range& e)
767 {
768 std::cerr << "No mapping for the events"
769 << std::endl;
770 }
771 }
772
773 if (sensorOffset > compositeSensorStates.size())
774 {
775 std::cerr
776 << " Error Invalid data, Invalid sensor offset"
777 << std::endl;
778 return;
779 }
780
781 const auto& possibleStates =
782 compositeSensorStates[sensorOffset];
783 if (possibleStates.find(eventState) ==
784 possibleStates.end())
785 {
786 std::cerr
787 << " Error invalid_data, Invalid event state"
788 << std::endl;
789 return;
790 }
791 const auto& [containerId, entityType, entityInstance] =
792 entityInfo;
793 pldm::responder::events::StateSensorEntry
794 stateSensorEntry{containerId, entityType,
795 entityInstance, sensorOffset};
796 handleStateSensorEvent(stateSensorEntry, eventState);
797 }
798 };
799
800 rc = handler->registerRequest(
801 mctp_eid, instanceId, PLDM_PLATFORM,
802 PLDM_GET_STATE_SENSOR_READINGS, std::move(requestMsg),
803 std::move(getStateSensorReadingRespHandler));
804
805 if (rc != PLDM_SUCCESS)
806 {
807 std::cerr << " Failed to send request to get State sensor "
808 "reading on Host "
809 << std::endl;
810 }
811 }
812 }
813 }
814}
Pavithra Barithaya51efaf82020-04-02 02:42:27 -0500815} // namespace pldm