blob: e74affc9a9f3cc9cc4a8e4be3345c78d7b09bf74 [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
Patrick Williams84b790c2022-07-22 19:26:56 -050093 hostOffMatch = std::make_unique<sdbusplus::bus::match_t>(
Deepak Kodihalli6b1d1ca2020-04-27 07:24:51 -050094 pldm::utils::DBusHandler::getBus(),
95 propertiesChanged("/xyz/openbmc_project/state/host0",
96 "xyz.openbmc_project.State.Host"),
Patrick Williams84b790c2022-07-22 19:26:56 -050097 [this, repo, entityTree, bmcEntityTree](sdbusplus::message_t& msg) {
Deepak Kodihalli6b1d1ca2020-04-27 07:24:51 -050098 DbusChangedProps props{};
99 std::string intf;
100 msg.read(intf, props);
101 const auto itr = props.find("CurrentHostState");
102 if (itr != props.end())
103 {
104 PropertyValue value = itr->second;
105 auto propVal = std::get<std::string>(value);
106 if (propVal == "xyz.openbmc_project.State.Host.HostState.Off")
107 {
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530108 // Delete all the remote terminus information
Manojkiran Eda8fee19a2021-11-15 12:07:44 +0530109 std::erase_if(tlPDRInfo, [](const auto& item) {
110 auto const& [key, value] = item;
111 return key != TERMINUS_HANDLE;
112 });
Deepak Kodihalli6b1d1ca2020-04-27 07:24:51 -0500113 pldm_pdr_remove_remote_pdrs(repo);
Sampa Misrac073a202021-05-08 10:56:05 -0500114 pldm_entity_association_tree_destroy_root(entityTree);
115 pldm_entity_association_tree_copy_root(bmcEntityTree,
116 entityTree);
Tom Josephb4268602020-04-17 17:20:45 +0530117 this->sensorMap.clear();
Pavithra Barithaya23025b92021-09-28 05:22:52 -0500118 this->responseReceived = false;
Deepak Kodihalli6b1d1ca2020-04-27 07:24:51 -0500119 }
120 }
121 });
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500122}
123
Deepak Kodihalli7246e0c2020-07-08 06:40:18 -0500124void HostPDRHandler::fetchPDR(PDRRecordHandles&& recordHandles)
Pavithra Barithaya51efaf82020-04-02 02:42:27 -0500125{
Deepak Kodihalli8cb6f662020-04-10 02:55:43 -0500126 pdrRecordHandles.clear();
127 pdrRecordHandles = std::move(recordHandles);
128
129 // Defer the actual fetch of PDRs from the host (by queuing the call on the
130 // main event loop). That way, we can respond to the platform event msg from
131 // the host firmware.
132 pdrFetchEvent = std::make_unique<sdeventplus::source::Defer>(
133 event, std::bind(std::mem_fn(&HostPDRHandler::_fetchPDR), this,
134 std::placeholders::_1));
135}
136
137void HostPDRHandler::_fetchPDR(sdeventplus::source::EventBase& /*source*/)
138{
Sampa Misrac0c79482021-06-02 08:01:54 -0500139 getHostPDR();
140}
141
142void HostPDRHandler::getHostPDR(uint32_t nextRecordHandle)
143{
Deepak Kodihalli8cb6f662020-04-10 02:55:43 -0500144 pdrFetchEvent.reset();
145
Pavithra Barithaya51efaf82020-04-02 02:42:27 -0500146 std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) +
147 PLDM_GET_PDR_REQ_BYTES);
148 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
Deepak Kodihalli7246e0c2020-07-08 06:40:18 -0500149 uint32_t recordHandle{};
Sampa Misrac0c79482021-06-02 08:01:54 -0500150 if (!nextRecordHandle)
Deepak Kodihalli7246e0c2020-07-08 06:40:18 -0500151 {
Sampa Misrac0c79482021-06-02 08:01:54 -0500152 if (!pdrRecordHandles.empty())
153 {
154 recordHandle = pdrRecordHandles.front();
155 pdrRecordHandles.pop_front();
156 }
157 }
158 else
159 {
160 recordHandle = nextRecordHandle;
161 }
162 auto instanceId = requester.getInstanceId(mctp_eid);
163
164 auto rc =
165 encode_get_pdr_req(instanceId, recordHandle, 0, PLDM_GET_FIRSTPART,
166 UINT16_MAX, 0, request, PLDM_GET_PDR_REQ_BYTES);
167 if (rc != PLDM_SUCCESS)
168 {
169 requester.markFree(mctp_eid, instanceId);
170 std::cerr << "Failed to encode_get_pdr_req, rc = " << rc << std::endl;
171 return;
172 }
Deepak Kodihalli7246e0c2020-07-08 06:40:18 -0500173
Sampa Misrac0c79482021-06-02 08:01:54 -0500174 rc = handler->registerRequest(
175 mctp_eid, instanceId, PLDM_PLATFORM, PLDM_GET_PDR,
176 std::move(requestMsg),
177 std::move(std::bind_front(&HostPDRHandler::processHostPDRs, this)));
178 if (rc)
Pavithra Barithaya51efaf82020-04-02 02:42:27 -0500179 {
Sampa Misrac0c79482021-06-02 08:01:54 -0500180 std::cerr << "Failed to send the GetPDR request to Host \n";
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500181 }
Pavithra Barithaya51efaf82020-04-02 02:42:27 -0500182}
183
Pavithra Barithaya3aec9972020-12-14 01:55:44 -0600184int HostPDRHandler::handleStateSensorEvent(const StateSensorEntry& entry,
185 pdr::EventState state)
186{
187 auto rc = stateSensorHandler.eventAction(entry, state);
188 if (rc != PLDM_SUCCESS)
189 {
190 std::cerr << "Failed to fetch and update D-bus property, rc = " << rc
191 << std::endl;
192 return rc;
193 }
194 return PLDM_SUCCESS;
195}
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500196bool HostPDRHandler::getParent(EntityType type, pldm_entity& parent)
197{
198 auto found = parents.find(type);
199 if (found != parents.end())
200 {
201 parent.entity_type = found->second.entity_type;
202 parent.entity_instance_num = found->second.entity_instance_num;
203 return true;
204 }
205
206 return false;
207}
208
209void HostPDRHandler::mergeEntityAssociations(const std::vector<uint8_t>& pdr)
210{
211 size_t numEntities{};
212 pldm_entity* entities = nullptr;
213 bool merged = false;
214 auto entityPdr = reinterpret_cast<pldm_pdr_entity_association*>(
215 const_cast<uint8_t*>(pdr.data()) + sizeof(pldm_pdr_hdr));
216
217 pldm_entity_association_pdr_extract(pdr.data(), pdr.size(), &numEntities,
218 &entities);
219 for (size_t i = 0; i < numEntities; ++i)
220 {
221 pldm_entity parent{};
222 if (getParent(entities[i].entity_type, parent))
223 {
224 auto node = pldm_entity_association_tree_find(entityTree, &parent);
225 if (node)
226 {
George Liu64a8f0f2021-06-12 10:56:11 +0800227 pldm_entity_association_tree_add(entityTree, &entities[i],
228 0xFFFF, node,
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500229 entityPdr->association_type);
230 merged = true;
231 }
232 }
233 }
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500234
235 if (merged)
236 {
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500237 // Update our PDR repo with the merged entity association PDRs
Sampa Misra719ed392021-06-04 05:15:13 -0500238 pldm_entity_node* node = nullptr;
239 pldm_find_entity_ref_in_tree(entityTree, entities[0], &node);
240 if (node == nullptr)
241 {
242 std::cerr
243 << "\ncould not find referrence of the entity in the tree \n";
244 }
245 else
246 {
Manojkiran Eda3ca40452021-10-04 22:51:37 +0530247 pldm_entity_association_pdr_add_from_node(
248 node, repo, &entities, numEntities, true, TERMINUS_HANDLE);
Sampa Misra719ed392021-06-04 05:15:13 -0500249 }
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500250 }
Sampa Misra719ed392021-06-04 05:15:13 -0500251 free(entities);
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500252}
253
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500254void HostPDRHandler::sendPDRRepositoryChgEvent(std::vector<uint8_t>&& pdrTypes,
255 uint8_t eventDataFormat)
256{
257 assert(eventDataFormat == FORMAT_IS_PDR_HANDLES);
258
259 // Extract from the PDR repo record handles of PDRs we want the host
260 // to pull up.
261 std::vector<uint8_t> eventDataOps{PLDM_RECORDS_ADDED};
262 std::vector<uint8_t> numsOfChangeEntries(1);
263 std::vector<std::vector<ChangeEntry>> changeEntries(
264 numsOfChangeEntries.size());
265 for (auto pdrType : pdrTypes)
266 {
267 const pldm_pdr_record* record{};
268 do
269 {
270 record = pldm_pdr_find_record_by_type(repo, pdrType, record,
271 nullptr, nullptr);
272 if (record && pldm_pdr_record_is_remote(record))
273 {
274 changeEntries[0].push_back(
275 pldm_pdr_get_record_handle(repo, record));
276 }
277 } while (record);
278 }
279 if (changeEntries.empty())
280 {
281 return;
282 }
283 numsOfChangeEntries[0] = changeEntries[0].size();
284
285 // Encode PLDM platform event msg to indicate a PDR repo change.
286 size_t maxSize = PLDM_PDR_REPOSITORY_CHG_EVENT_MIN_LENGTH +
287 PLDM_PDR_REPOSITORY_CHANGE_RECORD_MIN_LENGTH +
288 changeEntries[0].size() * sizeof(uint32_t);
289 std::vector<uint8_t> eventDataVec{};
290 eventDataVec.resize(maxSize);
291 auto eventData =
292 reinterpret_cast<struct pldm_pdr_repository_chg_event_data*>(
293 eventDataVec.data());
294 size_t actualSize{};
295 auto firstEntry = changeEntries[0].data();
296 auto rc = encode_pldm_pdr_repository_chg_event_data(
297 eventDataFormat, 1, eventDataOps.data(), numsOfChangeEntries.data(),
298 &firstEntry, eventData, &actualSize, maxSize);
299 if (rc != PLDM_SUCCESS)
300 {
301 std::cerr
302 << "Failed to encode_pldm_pdr_repository_chg_event_data, rc = "
303 << rc << std::endl;
304 return;
305 }
306 auto instanceId = requester.getInstanceId(mctp_eid);
307 std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) +
308 PLDM_PLATFORM_EVENT_MESSAGE_MIN_REQ_BYTES +
309 actualSize);
310 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
311 rc = encode_platform_event_message_req(
312 instanceId, 1, 0, PLDM_PDR_REPOSITORY_CHG_EVENT, eventDataVec.data(),
Christian Geddes3bdb3c22020-05-01 14:55:39 -0500313 actualSize, request,
314 actualSize + PLDM_PLATFORM_EVENT_MESSAGE_MIN_REQ_BYTES);
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500315 if (rc != PLDM_SUCCESS)
316 {
317 requester.markFree(mctp_eid, instanceId);
318 std::cerr << "Failed to encode_platform_event_message_req, rc = " << rc
319 << std::endl;
320 return;
321 }
322
Tom Joseph74f27c72021-05-16 07:58:53 -0700323 auto platformEventMessageResponseHandler = [](mctp_eid_t /*eid*/,
324 const pldm_msg* response,
325 size_t respMsgLen) {
326 if (response == nullptr || !respMsgLen)
327 {
328 std::cerr << "Failed to receive response for the PDR repository "
329 "changed event"
330 << "\n";
331 return;
332 }
333
334 uint8_t completionCode{};
335 uint8_t status{};
336 auto responsePtr = reinterpret_cast<const struct pldm_msg*>(response);
Pavithra Barithaya54b5a562021-09-27 06:07:10 -0500337 auto rc = decode_platform_event_message_resp(responsePtr, respMsgLen,
338 &completionCode, &status);
Sampa Misrac0c79482021-06-02 08:01:54 -0500339 if (rc || completionCode)
Tom Joseph74f27c72021-05-16 07:58:53 -0700340 {
341 std::cerr << "Failed to decode_platform_event_message_resp: "
342 << "rc=" << rc
343 << ", cc=" << static_cast<unsigned>(completionCode)
344 << std::endl;
345 }
346 };
347
Sampa Misrac0c79482021-06-02 08:01:54 -0500348 rc = handler->registerRequest(
Sampa Misra626c5652021-08-11 10:28:48 -0500349 mctp_eid, instanceId, PLDM_PLATFORM, PLDM_PLATFORM_EVENT_MESSAGE,
Tom Joseph74f27c72021-05-16 07:58:53 -0700350 std::move(requestMsg), std::move(platformEventMessageResponseHandler));
Sampa Misrac0c79482021-06-02 08:01:54 -0500351 if (rc)
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500352 {
Tom Joseph74f27c72021-05-16 07:58:53 -0700353 std::cerr << "Failed to send the PDR repository changed event request"
354 << "\n";
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500355 }
356}
357
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530358void HostPDRHandler::parseStateSensorPDRs(const PDRList& stateSensorPDRs)
Sampa Misra868c8792020-05-26 03:12:13 -0500359{
360 for (const auto& pdr : stateSensorPDRs)
361 {
362 SensorEntry sensorEntry{};
363 const auto& [terminusHandle, sensorID, sensorInfo] =
364 responder::pdr_utils::parseStateSensorPDR(pdr);
365 sensorEntry.sensorID = sensorID;
366 try
367 {
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530368 sensorEntry.terminusID = std::get<0>(tlPDRInfo.at(terminusHandle));
Sampa Misra868c8792020-05-26 03:12:13 -0500369 }
370 // If there is no mapping for terminusHandle assign the reserved TID
371 // value of 0xFF to indicate that.
372 catch (const std::out_of_range& e)
373 {
374 sensorEntry.terminusID = PLDM_TID_RESERVED;
375 }
376 sensorMap.emplace(sensorEntry, std::move(sensorInfo));
377 }
378}
379
Sampa Misrac0c79482021-06-02 08:01:54 -0500380void HostPDRHandler::processHostPDRs(mctp_eid_t /*eid*/,
381 const pldm_msg* response,
382 size_t respMsgLen)
383{
384 static bool merged = false;
385 static PDRList stateSensorPDRs{};
Sampa Misrac0c79482021-06-02 08:01:54 -0500386 uint32_t nextRecordHandle{};
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600387 uint8_t tlEid = 0;
388 bool tlValid = true;
389 uint32_t rh = 0;
390 uint16_t terminusHandle = 0;
Manojkiran Eda3ca40452021-10-04 22:51:37 +0530391 uint16_t pdrTerminusHandle = 0;
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600392 uint8_t tid = 0;
393
Sampa Misrac0c79482021-06-02 08:01:54 -0500394 uint8_t completionCode{};
395 uint32_t nextDataTransferHandle{};
396 uint8_t transferFlag{};
397 uint16_t respCount{};
398 uint8_t transferCRC{};
399 if (response == nullptr || !respMsgLen)
400 {
401 std::cerr << "Failed to receive response for the GetPDR"
402 " command \n";
403 return;
404 }
405
406 auto rc = decode_get_pdr_resp(
407 response, respMsgLen /*- sizeof(pldm_msg_hdr)*/, &completionCode,
408 &nextRecordHandle, &nextDataTransferHandle, &transferFlag, &respCount,
409 nullptr, 0, &transferCRC);
410 std::vector<uint8_t> responsePDRMsg;
411 responsePDRMsg.resize(respMsgLen + sizeof(pldm_msg_hdr));
412 memcpy(responsePDRMsg.data(), response, respMsgLen + sizeof(pldm_msg_hdr));
Sampa Misrac0c79482021-06-02 08:01:54 -0500413 if (rc != PLDM_SUCCESS)
414 {
415 std::cerr << "Failed to decode_get_pdr_resp, rc = " << rc << std::endl;
416 return;
417 }
418 else
419 {
420 std::vector<uint8_t> pdr(respCount, 0);
421 rc = decode_get_pdr_resp(response, respMsgLen, &completionCode,
422 &nextRecordHandle, &nextDataTransferHandle,
423 &transferFlag, &respCount, pdr.data(),
424 respCount, &transferCRC);
425 if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS)
426 {
427 std::cerr << "Failed to decode_get_pdr_resp: "
428 << "rc=" << rc
429 << ", cc=" << static_cast<unsigned>(completionCode)
430 << std::endl;
431 return;
432 }
433 else
434 {
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600435 // when nextRecordHandle is 0, we need the recordHandle of the last
436 // PDR and not 0-1.
437 if (!nextRecordHandle)
438 {
439 rh = nextRecordHandle;
440 }
441 else
442 {
443 rh = nextRecordHandle - 1;
444 }
445
Sampa Misrac0c79482021-06-02 08:01:54 -0500446 auto pdrHdr = reinterpret_cast<pldm_pdr_hdr*>(pdr.data());
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600447 if (!rh)
448 {
449 rh = pdrHdr->record_handle;
450 }
451
Sampa Misrac0c79482021-06-02 08:01:54 -0500452 if (pdrHdr->type == PLDM_PDR_ENTITY_ASSOCIATION)
453 {
454 this->mergeEntityAssociations(pdr);
455 merged = true;
456 }
457 else
458 {
459 if (pdrHdr->type == PLDM_TERMINUS_LOCATOR_PDR)
460 {
Manojkiran Eda3ca40452021-10-04 22:51:37 +0530461 pdrTerminusHandle =
462 extractTerminusHandle<pldm_terminus_locator_pdr>(pdr);
Sampa Misrac0c79482021-06-02 08:01:54 -0500463 auto tlpdr =
464 reinterpret_cast<const pldm_terminus_locator_pdr*>(
465 pdr.data());
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600466
467 terminusHandle = tlpdr->terminus_handle;
468 tid = tlpdr->tid;
469 auto terminus_locator_type = tlpdr->terminus_locator_type;
470 if (terminus_locator_type ==
471 PLDM_TERMINUS_LOCATOR_TYPE_MCTP_EID)
472 {
473 auto locatorValue = reinterpret_cast<
474 const pldm_terminus_locator_type_mctp_eid*>(
475 tlpdr->terminus_locator_value);
476 tlEid = static_cast<uint8_t>(locatorValue->eid);
477 }
478 if (tlpdr->validity == 0)
479 {
480 tlValid = false;
481 }
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530482 tlPDRInfo.insert_or_assign(
483 tlpdr->terminus_handle,
484 std::make_tuple(tlpdr->tid, tlEid, tlpdr->validity));
Sampa Misrac0c79482021-06-02 08:01:54 -0500485 }
486 else if (pdrHdr->type == PLDM_STATE_SENSOR_PDR)
487 {
Manojkiran Eda3ca40452021-10-04 22:51:37 +0530488 pdrTerminusHandle =
489 extractTerminusHandle<pldm_state_sensor_pdr>(pdr);
Sampa Misrac0c79482021-06-02 08:01:54 -0500490 stateSensorPDRs.emplace_back(pdr);
491 }
Manojkiran Eda3ca40452021-10-04 22:51:37 +0530492 else if (pdrHdr->type == PLDM_PDR_FRU_RECORD_SET)
493 {
494 pdrTerminusHandle =
495 extractTerminusHandle<pldm_pdr_fru_record_set>(pdr);
496 }
497 else if (pdrHdr->type == PLDM_STATE_EFFECTER_PDR)
498 {
499 pdrTerminusHandle =
500 extractTerminusHandle<pldm_state_effecter_pdr>(pdr);
501 }
502 else if (pdrHdr->type == PLDM_NUMERIC_EFFECTER_PDR)
503 {
504 pdrTerminusHandle =
505 extractTerminusHandle<pldm_numeric_effecter_value_pdr>(
506 pdr);
507 }
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600508 // if the TLPDR is invalid update the repo accordingly
509 if (!tlValid)
510 {
511 pldm_pdr_update_TL_pdr(repo, terminusHandle, tid, tlEid,
512 tlValid);
513 }
514 else
515 {
Manojkiran Eda3ca40452021-10-04 22:51:37 +0530516 pldm_pdr_add(repo, pdr.data(), respCount, rh, true,
517 pdrTerminusHandle);
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600518 }
Sampa Misrac0c79482021-06-02 08:01:54 -0500519 }
520 }
521 }
522 if (!nextRecordHandle)
523 {
524 /*received last record*/
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530525 this->parseStateSensorPDRs(stateSensorPDRs);
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600526 if (isHostUp())
527 {
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530528 this->setHostSensorState(stateSensorPDRs);
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600529 }
Sampa Misrac0c79482021-06-02 08:01:54 -0500530 stateSensorPDRs.clear();
Sampa Misrac0c79482021-06-02 08:01:54 -0500531 if (merged)
532 {
533 merged = false;
534 deferredPDRRepoChgEvent =
535 std::make_unique<sdeventplus::source::Defer>(
536 event,
537 std::bind(
538 std::mem_fn((&HostPDRHandler::_processPDRRepoChgEvent)),
539 this, std::placeholders::_1));
540 }
541 }
542 else
543 {
544 deferredFetchPDREvent = std::make_unique<sdeventplus::source::Defer>(
545 event,
546 std::bind(std::mem_fn((&HostPDRHandler::_processFetchPDREvent)),
547 this, nextRecordHandle, std::placeholders::_1));
548 }
549}
550
551void HostPDRHandler::_processPDRRepoChgEvent(
552 sdeventplus::source::EventBase& /*source */)
553{
554 deferredPDRRepoChgEvent.reset();
555 this->sendPDRRepositoryChgEvent(
556 std::move(std::vector<uint8_t>(1, PLDM_PDR_ENTITY_ASSOCIATION)),
557 FORMAT_IS_PDR_HANDLES);
558}
559
560void HostPDRHandler::_processFetchPDREvent(
561 uint32_t nextRecordHandle, sdeventplus::source::EventBase& /*source */)
562{
563 deferredFetchPDREvent.reset();
564 if (!this->pdrRecordHandles.empty())
565 {
566 nextRecordHandle = this->pdrRecordHandles.front();
567 this->pdrRecordHandles.pop_front();
568 }
569 this->getHostPDR(nextRecordHandle);
570}
571
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500572void HostPDRHandler::setHostFirmwareCondition()
sampmisr6decfc12021-03-02 11:07:36 +0530573{
sampmisr6decfc12021-03-02 11:07:36 +0530574 responseReceived = false;
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500575 auto instanceId = requester.getInstanceId(mctp_eid);
576 std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) +
577 PLDM_GET_VERSION_REQ_BYTES);
578 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
579 auto rc = encode_get_version_req(instanceId, 0, PLDM_GET_FIRSTPART,
580 PLDM_BASE, request);
581 if (rc != PLDM_SUCCESS)
sampmisr6decfc12021-03-02 11:07:36 +0530582 {
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500583 std::cerr << "GetPLDMVersion encode failure. PLDM error code = "
584 << std::hex << std::showbase << rc << "\n";
585 requester.markFree(mctp_eid, instanceId);
sampmisr6decfc12021-03-02 11:07:36 +0530586 return;
587 }
588
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500589 auto getPLDMVersionHandler = [this](mctp_eid_t /*eid*/,
590 const pldm_msg* response,
591 size_t respMsgLen) {
592 if (response == nullptr || !respMsgLen)
sampmisr6decfc12021-03-02 11:07:36 +0530593 {
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500594 std::cerr << "Failed to receive response for "
595 << "getPLDMVersion command, Host seems to be off \n";
sampmisr6decfc12021-03-02 11:07:36 +0530596 return;
597 }
sampmisr6decfc12021-03-02 11:07:36 +0530598 std::cout << "Getting the response. PLDM RC = " << std::hex
599 << std::showbase
600 << static_cast<uint16_t>(response->payload[0]) << "\n";
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500601 this->responseReceived = true;
602 getHostPDR();
sampmisr6decfc12021-03-02 11:07:36 +0530603 };
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500604 rc = handler->registerRequest(mctp_eid, instanceId, PLDM_BASE,
605 PLDM_GET_PLDM_VERSION, std::move(requestMsg),
606 std::move(getPLDMVersionHandler));
607 if (rc)
sampmisr6decfc12021-03-02 11:07:36 +0530608 {
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500609 std::cerr << "Failed to discover Host state. Assuming Host as off \n";
sampmisr6decfc12021-03-02 11:07:36 +0530610 }
611}
612
613bool HostPDRHandler::isHostUp()
614{
615 return responseReceived;
616}
617
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530618void HostPDRHandler::setHostSensorState(const PDRList& stateSensorPDRs)
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600619{
620 for (const auto& stateSensorPDR : stateSensorPDRs)
621 {
622 auto pdr = reinterpret_cast<const pldm_state_sensor_pdr*>(
623 stateSensorPDR.data());
624
625 if (!pdr)
626 {
627 std::cerr << "Failed to get State sensor PDR" << std::endl;
628 pldm::utils::reportError(
629 "xyz.openbmc_project.bmc.pldm.InternalFailure");
630 return;
631 }
632
633 uint16_t sensorId = pdr->sensor_id;
634
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530635 for (const auto& [terminusHandle, terminusInfo] : tlPDRInfo)
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600636 {
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530637 if (terminusHandle == pdr->terminus_handle)
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600638 {
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530639 if (std::get<2>(terminusInfo) == PLDM_TL_PDR_VALID)
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600640 {
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530641 mctp_eid = std::get<1>(terminusInfo);
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600642 }
643
644 bitfield8_t sensorRearm;
645 sensorRearm.byte = 0;
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530646 uint8_t tid = std::get<0>(terminusInfo);
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600647
648 auto instanceId = requester.getInstanceId(mctp_eid);
649 std::vector<uint8_t> requestMsg(
650 sizeof(pldm_msg_hdr) +
651 PLDM_GET_STATE_SENSOR_READINGS_REQ_BYTES);
652 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
653 auto rc = encode_get_state_sensor_readings_req(
654 instanceId, sensorId, sensorRearm, 0, request);
655
656 if (rc != PLDM_SUCCESS)
657 {
658 requester.markFree(mctp_eid, instanceId);
659 std::cerr << "Failed to "
660 "encode_get_state_sensor_readings_req, rc = "
661 << rc << std::endl;
662 pldm::utils::reportError(
663 "xyz.openbmc_project.bmc.pldm.InternalFailure");
664 return;
665 }
666
667 auto getStateSensorReadingRespHandler = [=, this](
668 mctp_eid_t /*eid*/,
669 const pldm_msg*
670 response,
671 size_t respMsgLen) {
672 if (response == nullptr || !respMsgLen)
673 {
674 std::cerr << "Failed to receive response for "
675 "getStateSensorReading command \n";
676 return;
677 }
678 std::array<get_sensor_state_field, 8> stateField{};
679 uint8_t completionCode = 0;
680 uint8_t comp_sensor_count = 0;
681
682 auto rc = decode_get_state_sensor_readings_resp(
683 response, respMsgLen, &completionCode,
684 &comp_sensor_count, stateField.data());
685
686 if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS)
687 {
688 std::cerr
689 << "Failed to "
690 "decode_get_state_sensor_readings_resp, rc = "
691 << rc
692 << " cc=" << static_cast<unsigned>(completionCode)
693 << std::endl;
694 pldm::utils::reportError(
695 "xyz.openbmc_project.bmc.pldm.InternalFailure");
696 }
697
698 uint8_t eventState;
699 uint8_t previousEventState;
700 uint8_t sensorOffset = comp_sensor_count - 1;
701
702 for (size_t i = 0; i < comp_sensor_count; i++)
703 {
704 eventState = stateField[i].present_state;
705 previousEventState = stateField[i].previous_state;
706
707 emitStateSensorEventSignal(tid, sensorId, sensorOffset,
708 eventState,
709 previousEventState);
710
711 SensorEntry sensorEntry{tid, sensorId};
712
713 pldm::pdr::EntityInfo entityInfo{};
714 pldm::pdr::CompositeSensorStates
715 compositeSensorStates{};
716
717 try
718 {
719 std::tie(entityInfo, compositeSensorStates) =
720 lookupSensorInfo(sensorEntry);
721 }
722 catch (const std::out_of_range& e)
723 {
724 try
725 {
726 sensorEntry.terminusID = PLDM_TID_RESERVED;
727 std::tie(entityInfo, compositeSensorStates) =
728 lookupSensorInfo(sensorEntry);
729 }
730 catch (const std::out_of_range& e)
731 {
732 std::cerr << "No mapping for the events"
733 << std::endl;
734 }
735 }
736
737 if (sensorOffset > compositeSensorStates.size())
738 {
739 std::cerr
740 << " Error Invalid data, Invalid sensor offset"
741 << std::endl;
742 return;
743 }
744
745 const auto& possibleStates =
746 compositeSensorStates[sensorOffset];
747 if (possibleStates.find(eventState) ==
748 possibleStates.end())
749 {
750 std::cerr
751 << " Error invalid_data, Invalid event state"
752 << std::endl;
753 return;
754 }
755 const auto& [containerId, entityType, entityInstance] =
756 entityInfo;
757 pldm::responder::events::StateSensorEntry
758 stateSensorEntry{containerId, entityType,
759 entityInstance, sensorOffset};
760 handleStateSensorEvent(stateSensorEntry, eventState);
761 }
762 };
763
764 rc = handler->registerRequest(
765 mctp_eid, instanceId, PLDM_PLATFORM,
766 PLDM_GET_STATE_SENSOR_READINGS, std::move(requestMsg),
767 std::move(getStateSensorReadingRespHandler));
768
769 if (rc != PLDM_SUCCESS)
770 {
771 std::cerr << " Failed to send request to get State sensor "
772 "reading on Host "
773 << std::endl;
774 }
775 }
776 }
777 }
778}
Pavithra Barithaya51efaf82020-04-02 02:42:27 -0500779} // namespace pldm