blob: 0cc8a1af7083ba4e55285bc78aea73f7462f6a7c [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{
Brad Bishop5079ac42021-08-19 18:35:06 -040019using namespace pldm::dbus_api;
20using namespace pldm::responder::events;
Deepak Kodihalli6b1d1ca2020-04-27 07:24:51 -050021using namespace pldm::utils;
22using namespace sdbusplus::bus::match::rules;
Deepak Kodihalli87514cc2020-04-16 09:08:38 -050023using Json = nlohmann::json;
24namespace fs = std::filesystem;
25constexpr auto fruJson = "host_frus.json";
26const Json emptyJson{};
27const std::vector<Json> emptyJsonList{};
28
Manojkiran Eda3ca40452021-10-04 22:51:37 +053029template <typename T>
30uint16_t extractTerminusHandle(std::vector<uint8_t>& pdr)
31{
32 T* var = nullptr;
33 if (std::is_same<T, pldm_pdr_fru_record_set>::value)
34 {
35 var = (T*)(pdr.data() + sizeof(pldm_pdr_hdr));
36 }
37 else
38 {
39 var = (T*)(pdr.data());
40 }
41 if (var != nullptr)
42 {
43 return var->terminus_handle;
44 }
45 return TERMINUS_HANDLE;
46}
47
Tom Joseph74f27c72021-05-16 07:58:53 -070048HostPDRHandler::HostPDRHandler(
49 int mctp_fd, uint8_t mctp_eid, sdeventplus::Event& event, pldm_pdr* repo,
50 const std::string& eventsJsonsDir, pldm_entity_association_tree* entityTree,
51 pldm_entity_association_tree* bmcEntityTree, Requester& requester,
Tom Josephe5268cd2021-09-07 13:04:03 +053052 pldm::requester::Handler<pldm::requester::Request>* handler) :
Deepak Kodihalli87514cc2020-04-16 09:08:38 -050053 mctp_fd(mctp_fd),
Pavithra Barithaya3aec9972020-12-14 01:55:44 -060054 mctp_eid(mctp_eid), event(event), repo(repo),
55 stateSensorHandler(eventsJsonsDir), entityTree(entityTree),
Tom Josephe5268cd2021-09-07 13:04:03 +053056 bmcEntityTree(bmcEntityTree), requester(requester), handler(handler)
Deepak Kodihalli87514cc2020-04-16 09:08:38 -050057{
58 fs::path hostFruJson(fs::path(HOST_JSONS_DIR) / fruJson);
59 if (fs::exists(hostFruJson))
60 {
Pavithra Barithayae8beb892020-04-14 23:24:25 -050061 // Note parent entities for entities sent down by the host firmware.
62 // This will enable a merge of entity associations.
Deepak Kodihalli87514cc2020-04-16 09:08:38 -050063 try
64 {
65 std::ifstream jsonFile(hostFruJson);
66 auto data = Json::parse(jsonFile, nullptr, false);
67 if (data.is_discarded())
68 {
69 std::cerr << "Parsing Host FRU json file failed" << std::endl;
70 }
71 else
72 {
73 auto entities = data.value("entities", emptyJsonList);
74 for (auto& entity : entities)
75 {
76 EntityType entityType = entity.value("entity_type", 0);
77 auto parent = entity.value("parent", emptyJson);
78 pldm_entity p{};
79 p.entity_type = parent.value("entity_type", 0);
80 p.entity_instance_num = parent.value("entity_instance", 0);
81 parents.emplace(entityType, std::move(p));
82 }
83 }
84 }
85 catch (const std::exception& e)
86 {
87 std::cerr << "Parsing Host FRU json file failed, exception = "
88 << e.what() << std::endl;
89 }
90 }
Deepak Kodihalli6b1d1ca2020-04-27 07:24:51 -050091
Patrick Williams84b790c2022-07-22 19:26:56 -050092 hostOffMatch = std::make_unique<sdbusplus::bus::match_t>(
Deepak Kodihalli6b1d1ca2020-04-27 07:24:51 -050093 pldm::utils::DBusHandler::getBus(),
94 propertiesChanged("/xyz/openbmc_project/state/host0",
95 "xyz.openbmc_project.State.Host"),
Patrick Williams84b790c2022-07-22 19:26:56 -050096 [this, repo, entityTree, bmcEntityTree](sdbusplus::message_t& msg) {
Deepak Kodihalli6b1d1ca2020-04-27 07:24:51 -050097 DbusChangedProps props{};
98 std::string intf;
99 msg.read(intf, props);
100 const auto itr = props.find("CurrentHostState");
101 if (itr != props.end())
102 {
103 PropertyValue value = itr->second;
104 auto propVal = std::get<std::string>(value);
105 if (propVal == "xyz.openbmc_project.State.Host.HostState.Off")
106 {
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530107 // Delete all the remote terminus information
Manojkiran Eda8fee19a2021-11-15 12:07:44 +0530108 std::erase_if(tlPDRInfo, [](const auto& item) {
109 auto const& [key, value] = item;
110 return key != TERMINUS_HANDLE;
111 });
Deepak Kodihalli6b1d1ca2020-04-27 07:24:51 -0500112 pldm_pdr_remove_remote_pdrs(repo);
Sampa Misrac073a202021-05-08 10:56:05 -0500113 pldm_entity_association_tree_destroy_root(entityTree);
114 pldm_entity_association_tree_copy_root(bmcEntityTree,
115 entityTree);
Tom Josephb4268602020-04-17 17:20:45 +0530116 this->sensorMap.clear();
Pavithra Barithaya23025b92021-09-28 05:22:52 -0500117 this->responseReceived = false;
Deepak Kodihalli6b1d1ca2020-04-27 07:24:51 -0500118 }
119 }
120 });
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500121}
122
Deepak Kodihalli7246e0c2020-07-08 06:40:18 -0500123void HostPDRHandler::fetchPDR(PDRRecordHandles&& recordHandles)
Pavithra Barithaya51efaf82020-04-02 02:42:27 -0500124{
Deepak Kodihalli8cb6f662020-04-10 02:55:43 -0500125 pdrRecordHandles.clear();
126 pdrRecordHandles = std::move(recordHandles);
127
128 // Defer the actual fetch of PDRs from the host (by queuing the call on the
129 // main event loop). That way, we can respond to the platform event msg from
130 // the host firmware.
131 pdrFetchEvent = std::make_unique<sdeventplus::source::Defer>(
132 event, std::bind(std::mem_fn(&HostPDRHandler::_fetchPDR), this,
133 std::placeholders::_1));
134}
135
136void HostPDRHandler::_fetchPDR(sdeventplus::source::EventBase& /*source*/)
137{
Sampa Misrac0c79482021-06-02 08:01:54 -0500138 getHostPDR();
139}
140
141void HostPDRHandler::getHostPDR(uint32_t nextRecordHandle)
142{
Deepak Kodihalli8cb6f662020-04-10 02:55:43 -0500143 pdrFetchEvent.reset();
144
Pavithra Barithaya51efaf82020-04-02 02:42:27 -0500145 std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) +
146 PLDM_GET_PDR_REQ_BYTES);
147 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
Deepak Kodihalli7246e0c2020-07-08 06:40:18 -0500148 uint32_t recordHandle{};
Sampa Misrac0c79482021-06-02 08:01:54 -0500149 if (!nextRecordHandle)
Deepak Kodihalli7246e0c2020-07-08 06:40:18 -0500150 {
Sampa Misrac0c79482021-06-02 08:01:54 -0500151 if (!pdrRecordHandles.empty())
152 {
153 recordHandle = pdrRecordHandles.front();
154 pdrRecordHandles.pop_front();
155 }
156 }
157 else
158 {
159 recordHandle = nextRecordHandle;
160 }
161 auto instanceId = requester.getInstanceId(mctp_eid);
162
163 auto rc =
164 encode_get_pdr_req(instanceId, recordHandle, 0, PLDM_GET_FIRSTPART,
165 UINT16_MAX, 0, request, PLDM_GET_PDR_REQ_BYTES);
166 if (rc != PLDM_SUCCESS)
167 {
168 requester.markFree(mctp_eid, instanceId);
169 std::cerr << "Failed to encode_get_pdr_req, rc = " << rc << std::endl;
170 return;
171 }
Deepak Kodihalli7246e0c2020-07-08 06:40:18 -0500172
Sampa Misrac0c79482021-06-02 08:01:54 -0500173 rc = handler->registerRequest(
174 mctp_eid, instanceId, PLDM_PLATFORM, PLDM_GET_PDR,
175 std::move(requestMsg),
176 std::move(std::bind_front(&HostPDRHandler::processHostPDRs, this)));
177 if (rc)
Pavithra Barithaya51efaf82020-04-02 02:42:27 -0500178 {
Sampa Misrac0c79482021-06-02 08:01:54 -0500179 std::cerr << "Failed to send the GetPDR request to Host \n";
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500180 }
Pavithra Barithaya51efaf82020-04-02 02:42:27 -0500181}
182
Pavithra Barithaya3aec9972020-12-14 01:55:44 -0600183int HostPDRHandler::handleStateSensorEvent(const StateSensorEntry& entry,
184 pdr::EventState state)
185{
186 auto rc = stateSensorHandler.eventAction(entry, state);
187 if (rc != PLDM_SUCCESS)
188 {
189 std::cerr << "Failed to fetch and update D-bus property, rc = " << rc
190 << std::endl;
191 return rc;
192 }
193 return PLDM_SUCCESS;
194}
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500195bool HostPDRHandler::getParent(EntityType type, pldm_entity& parent)
196{
197 auto found = parents.find(type);
198 if (found != parents.end())
199 {
200 parent.entity_type = found->second.entity_type;
201 parent.entity_instance_num = found->second.entity_instance_num;
202 return true;
203 }
204
205 return false;
206}
207
208void HostPDRHandler::mergeEntityAssociations(const std::vector<uint8_t>& pdr)
209{
210 size_t numEntities{};
211 pldm_entity* entities = nullptr;
212 bool merged = false;
213 auto entityPdr = reinterpret_cast<pldm_pdr_entity_association*>(
214 const_cast<uint8_t*>(pdr.data()) + sizeof(pldm_pdr_hdr));
215
216 pldm_entity_association_pdr_extract(pdr.data(), pdr.size(), &numEntities,
217 &entities);
218 for (size_t i = 0; i < numEntities; ++i)
219 {
220 pldm_entity parent{};
221 if (getParent(entities[i].entity_type, parent))
222 {
223 auto node = pldm_entity_association_tree_find(entityTree, &parent);
224 if (node)
225 {
George Liu64a8f0f2021-06-12 10:56:11 +0800226 pldm_entity_association_tree_add(entityTree, &entities[i],
227 0xFFFF, node,
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500228 entityPdr->association_type);
229 merged = true;
230 }
231 }
232 }
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500233
234 if (merged)
235 {
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500236 // Update our PDR repo with the merged entity association PDRs
Sampa Misra719ed392021-06-04 05:15:13 -0500237 pldm_entity_node* node = nullptr;
238 pldm_find_entity_ref_in_tree(entityTree, entities[0], &node);
239 if (node == nullptr)
240 {
241 std::cerr
242 << "\ncould not find referrence of the entity in the tree \n";
243 }
244 else
245 {
Manojkiran Eda3ca40452021-10-04 22:51:37 +0530246 pldm_entity_association_pdr_add_from_node(
247 node, repo, &entities, numEntities, true, TERMINUS_HANDLE);
Sampa Misra719ed392021-06-04 05:15:13 -0500248 }
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500249 }
Sampa Misra719ed392021-06-04 05:15:13 -0500250 free(entities);
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500251}
252
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500253void HostPDRHandler::sendPDRRepositoryChgEvent(std::vector<uint8_t>&& pdrTypes,
254 uint8_t eventDataFormat)
255{
256 assert(eventDataFormat == FORMAT_IS_PDR_HANDLES);
257
258 // Extract from the PDR repo record handles of PDRs we want the host
259 // to pull up.
260 std::vector<uint8_t> eventDataOps{PLDM_RECORDS_ADDED};
261 std::vector<uint8_t> numsOfChangeEntries(1);
262 std::vector<std::vector<ChangeEntry>> changeEntries(
263 numsOfChangeEntries.size());
264 for (auto pdrType : pdrTypes)
265 {
266 const pldm_pdr_record* record{};
267 do
268 {
269 record = pldm_pdr_find_record_by_type(repo, pdrType, record,
270 nullptr, nullptr);
271 if (record && pldm_pdr_record_is_remote(record))
272 {
273 changeEntries[0].push_back(
274 pldm_pdr_get_record_handle(repo, record));
275 }
276 } while (record);
277 }
278 if (changeEntries.empty())
279 {
280 return;
281 }
282 numsOfChangeEntries[0] = changeEntries[0].size();
283
284 // Encode PLDM platform event msg to indicate a PDR repo change.
285 size_t maxSize = PLDM_PDR_REPOSITORY_CHG_EVENT_MIN_LENGTH +
286 PLDM_PDR_REPOSITORY_CHANGE_RECORD_MIN_LENGTH +
287 changeEntries[0].size() * sizeof(uint32_t);
288 std::vector<uint8_t> eventDataVec{};
289 eventDataVec.resize(maxSize);
290 auto eventData =
291 reinterpret_cast<struct pldm_pdr_repository_chg_event_data*>(
292 eventDataVec.data());
293 size_t actualSize{};
294 auto firstEntry = changeEntries[0].data();
295 auto rc = encode_pldm_pdr_repository_chg_event_data(
296 eventDataFormat, 1, eventDataOps.data(), numsOfChangeEntries.data(),
297 &firstEntry, eventData, &actualSize, maxSize);
298 if (rc != PLDM_SUCCESS)
299 {
300 std::cerr
301 << "Failed to encode_pldm_pdr_repository_chg_event_data, rc = "
302 << rc << std::endl;
303 return;
304 }
305 auto instanceId = requester.getInstanceId(mctp_eid);
306 std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) +
307 PLDM_PLATFORM_EVENT_MESSAGE_MIN_REQ_BYTES +
308 actualSize);
309 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
310 rc = encode_platform_event_message_req(
311 instanceId, 1, 0, PLDM_PDR_REPOSITORY_CHG_EVENT, eventDataVec.data(),
Christian Geddes3bdb3c22020-05-01 14:55:39 -0500312 actualSize, request,
313 actualSize + PLDM_PLATFORM_EVENT_MESSAGE_MIN_REQ_BYTES);
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500314 if (rc != PLDM_SUCCESS)
315 {
316 requester.markFree(mctp_eid, instanceId);
317 std::cerr << "Failed to encode_platform_event_message_req, rc = " << rc
318 << std::endl;
319 return;
320 }
321
Tom Joseph74f27c72021-05-16 07:58:53 -0700322 auto platformEventMessageResponseHandler = [](mctp_eid_t /*eid*/,
323 const pldm_msg* response,
324 size_t respMsgLen) {
325 if (response == nullptr || !respMsgLen)
326 {
327 std::cerr << "Failed to receive response for the PDR repository "
328 "changed event"
329 << "\n";
330 return;
331 }
332
333 uint8_t completionCode{};
334 uint8_t status{};
335 auto responsePtr = reinterpret_cast<const struct pldm_msg*>(response);
Pavithra Barithaya54b5a562021-09-27 06:07:10 -0500336 auto rc = decode_platform_event_message_resp(responsePtr, respMsgLen,
337 &completionCode, &status);
Sampa Misrac0c79482021-06-02 08:01:54 -0500338 if (rc || completionCode)
Tom Joseph74f27c72021-05-16 07:58:53 -0700339 {
340 std::cerr << "Failed to decode_platform_event_message_resp: "
341 << "rc=" << rc
342 << ", cc=" << static_cast<unsigned>(completionCode)
343 << std::endl;
344 }
345 };
346
Sampa Misrac0c79482021-06-02 08:01:54 -0500347 rc = handler->registerRequest(
Sampa Misra626c5652021-08-11 10:28:48 -0500348 mctp_eid, instanceId, PLDM_PLATFORM, PLDM_PLATFORM_EVENT_MESSAGE,
Tom Joseph74f27c72021-05-16 07:58:53 -0700349 std::move(requestMsg), std::move(platformEventMessageResponseHandler));
Sampa Misrac0c79482021-06-02 08:01:54 -0500350 if (rc)
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500351 {
Tom Joseph74f27c72021-05-16 07:58:53 -0700352 std::cerr << "Failed to send the PDR repository changed event request"
353 << "\n";
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500354 }
355}
356
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530357void HostPDRHandler::parseStateSensorPDRs(const PDRList& stateSensorPDRs)
Sampa Misra868c8792020-05-26 03:12:13 -0500358{
359 for (const auto& pdr : stateSensorPDRs)
360 {
361 SensorEntry sensorEntry{};
362 const auto& [terminusHandle, sensorID, sensorInfo] =
363 responder::pdr_utils::parseStateSensorPDR(pdr);
364 sensorEntry.sensorID = sensorID;
365 try
366 {
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530367 sensorEntry.terminusID = std::get<0>(tlPDRInfo.at(terminusHandle));
Sampa Misra868c8792020-05-26 03:12:13 -0500368 }
369 // If there is no mapping for terminusHandle assign the reserved TID
370 // value of 0xFF to indicate that.
371 catch (const std::out_of_range& e)
372 {
373 sensorEntry.terminusID = PLDM_TID_RESERVED;
374 }
375 sensorMap.emplace(sensorEntry, std::move(sensorInfo));
376 }
377}
378
Sampa Misrac0c79482021-06-02 08:01:54 -0500379void HostPDRHandler::processHostPDRs(mctp_eid_t /*eid*/,
380 const pldm_msg* response,
381 size_t respMsgLen)
382{
383 static bool merged = false;
384 static PDRList stateSensorPDRs{};
Sampa Misrac0c79482021-06-02 08:01:54 -0500385 uint32_t nextRecordHandle{};
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600386 uint8_t tlEid = 0;
387 bool tlValid = true;
388 uint32_t rh = 0;
389 uint16_t terminusHandle = 0;
Manojkiran Eda3ca40452021-10-04 22:51:37 +0530390 uint16_t pdrTerminusHandle = 0;
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600391 uint8_t tid = 0;
392
Sampa Misrac0c79482021-06-02 08:01:54 -0500393 uint8_t completionCode{};
394 uint32_t nextDataTransferHandle{};
395 uint8_t transferFlag{};
396 uint16_t respCount{};
397 uint8_t transferCRC{};
398 if (response == nullptr || !respMsgLen)
399 {
400 std::cerr << "Failed to receive response for the GetPDR"
401 " command \n";
402 return;
403 }
404
405 auto rc = decode_get_pdr_resp(
406 response, respMsgLen /*- sizeof(pldm_msg_hdr)*/, &completionCode,
407 &nextRecordHandle, &nextDataTransferHandle, &transferFlag, &respCount,
408 nullptr, 0, &transferCRC);
409 std::vector<uint8_t> responsePDRMsg;
410 responsePDRMsg.resize(respMsgLen + sizeof(pldm_msg_hdr));
411 memcpy(responsePDRMsg.data(), response, respMsgLen + sizeof(pldm_msg_hdr));
Sampa Misrac0c79482021-06-02 08:01:54 -0500412 if (rc != PLDM_SUCCESS)
413 {
414 std::cerr << "Failed to decode_get_pdr_resp, rc = " << rc << std::endl;
415 return;
416 }
417 else
418 {
419 std::vector<uint8_t> pdr(respCount, 0);
420 rc = decode_get_pdr_resp(response, respMsgLen, &completionCode,
421 &nextRecordHandle, &nextDataTransferHandle,
422 &transferFlag, &respCount, pdr.data(),
423 respCount, &transferCRC);
424 if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS)
425 {
426 std::cerr << "Failed to decode_get_pdr_resp: "
427 << "rc=" << rc
428 << ", cc=" << static_cast<unsigned>(completionCode)
429 << std::endl;
430 return;
431 }
432 else
433 {
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600434 // when nextRecordHandle is 0, we need the recordHandle of the last
435 // PDR and not 0-1.
436 if (!nextRecordHandle)
437 {
438 rh = nextRecordHandle;
439 }
440 else
441 {
442 rh = nextRecordHandle - 1;
443 }
444
Sampa Misrac0c79482021-06-02 08:01:54 -0500445 auto pdrHdr = reinterpret_cast<pldm_pdr_hdr*>(pdr.data());
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600446 if (!rh)
447 {
448 rh = pdrHdr->record_handle;
449 }
450
Sampa Misrac0c79482021-06-02 08:01:54 -0500451 if (pdrHdr->type == PLDM_PDR_ENTITY_ASSOCIATION)
452 {
453 this->mergeEntityAssociations(pdr);
454 merged = true;
455 }
456 else
457 {
458 if (pdrHdr->type == PLDM_TERMINUS_LOCATOR_PDR)
459 {
Manojkiran Eda3ca40452021-10-04 22:51:37 +0530460 pdrTerminusHandle =
461 extractTerminusHandle<pldm_terminus_locator_pdr>(pdr);
Sampa Misrac0c79482021-06-02 08:01:54 -0500462 auto tlpdr =
463 reinterpret_cast<const pldm_terminus_locator_pdr*>(
464 pdr.data());
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600465
466 terminusHandle = tlpdr->terminus_handle;
467 tid = tlpdr->tid;
468 auto terminus_locator_type = tlpdr->terminus_locator_type;
469 if (terminus_locator_type ==
470 PLDM_TERMINUS_LOCATOR_TYPE_MCTP_EID)
471 {
472 auto locatorValue = reinterpret_cast<
473 const pldm_terminus_locator_type_mctp_eid*>(
474 tlpdr->terminus_locator_value);
475 tlEid = static_cast<uint8_t>(locatorValue->eid);
476 }
477 if (tlpdr->validity == 0)
478 {
479 tlValid = false;
480 }
Pavithra Barithaya52aad392022-08-02 04:18:52 -0500481 for (const auto& terminusMap : tlPDRInfo)
482 {
483 if ((terminusHandle == (terminusMap.first)) &&
484 (get<1>(terminusMap.second) == tlEid) &&
485 (get<2>(terminusMap.second) == tlpdr->validity))
486 {
487 // TL PDR already present with same validity don't
488 // add the PDR to the repo just return
489 return;
490 }
491 }
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530492 tlPDRInfo.insert_or_assign(
493 tlpdr->terminus_handle,
494 std::make_tuple(tlpdr->tid, tlEid, tlpdr->validity));
Sampa Misrac0c79482021-06-02 08:01:54 -0500495 }
496 else if (pdrHdr->type == PLDM_STATE_SENSOR_PDR)
497 {
Manojkiran Eda3ca40452021-10-04 22:51:37 +0530498 pdrTerminusHandle =
499 extractTerminusHandle<pldm_state_sensor_pdr>(pdr);
Sampa Misrac0c79482021-06-02 08:01:54 -0500500 stateSensorPDRs.emplace_back(pdr);
501 }
Manojkiran Eda3ca40452021-10-04 22:51:37 +0530502 else if (pdrHdr->type == PLDM_PDR_FRU_RECORD_SET)
503 {
504 pdrTerminusHandle =
505 extractTerminusHandle<pldm_pdr_fru_record_set>(pdr);
506 }
507 else if (pdrHdr->type == PLDM_STATE_EFFECTER_PDR)
508 {
509 pdrTerminusHandle =
510 extractTerminusHandle<pldm_state_effecter_pdr>(pdr);
511 }
512 else if (pdrHdr->type == PLDM_NUMERIC_EFFECTER_PDR)
513 {
514 pdrTerminusHandle =
515 extractTerminusHandle<pldm_numeric_effecter_value_pdr>(
516 pdr);
517 }
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600518 // if the TLPDR is invalid update the repo accordingly
519 if (!tlValid)
520 {
521 pldm_pdr_update_TL_pdr(repo, terminusHandle, tid, tlEid,
522 tlValid);
523 }
524 else
525 {
Manojkiran Eda3ca40452021-10-04 22:51:37 +0530526 pldm_pdr_add(repo, pdr.data(), respCount, rh, true,
527 pdrTerminusHandle);
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600528 }
Sampa Misrac0c79482021-06-02 08:01:54 -0500529 }
530 }
531 }
532 if (!nextRecordHandle)
533 {
534 /*received last record*/
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530535 this->parseStateSensorPDRs(stateSensorPDRs);
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600536 if (isHostUp())
537 {
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530538 this->setHostSensorState(stateSensorPDRs);
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600539 }
Sampa Misrac0c79482021-06-02 08:01:54 -0500540 stateSensorPDRs.clear();
Sampa Misrac0c79482021-06-02 08:01:54 -0500541 if (merged)
542 {
543 merged = false;
544 deferredPDRRepoChgEvent =
545 std::make_unique<sdeventplus::source::Defer>(
546 event,
547 std::bind(
548 std::mem_fn((&HostPDRHandler::_processPDRRepoChgEvent)),
549 this, std::placeholders::_1));
550 }
551 }
552 else
553 {
554 deferredFetchPDREvent = std::make_unique<sdeventplus::source::Defer>(
555 event,
556 std::bind(std::mem_fn((&HostPDRHandler::_processFetchPDREvent)),
557 this, nextRecordHandle, std::placeholders::_1));
558 }
559}
560
561void HostPDRHandler::_processPDRRepoChgEvent(
562 sdeventplus::source::EventBase& /*source */)
563{
564 deferredPDRRepoChgEvent.reset();
565 this->sendPDRRepositoryChgEvent(
566 std::move(std::vector<uint8_t>(1, PLDM_PDR_ENTITY_ASSOCIATION)),
567 FORMAT_IS_PDR_HANDLES);
568}
569
570void HostPDRHandler::_processFetchPDREvent(
571 uint32_t nextRecordHandle, sdeventplus::source::EventBase& /*source */)
572{
573 deferredFetchPDREvent.reset();
574 if (!this->pdrRecordHandles.empty())
575 {
576 nextRecordHandle = this->pdrRecordHandles.front();
577 this->pdrRecordHandles.pop_front();
578 }
579 this->getHostPDR(nextRecordHandle);
580}
581
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500582void HostPDRHandler::setHostFirmwareCondition()
sampmisr6decfc12021-03-02 11:07:36 +0530583{
sampmisr6decfc12021-03-02 11:07:36 +0530584 responseReceived = false;
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500585 auto instanceId = requester.getInstanceId(mctp_eid);
586 std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) +
587 PLDM_GET_VERSION_REQ_BYTES);
588 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
589 auto rc = encode_get_version_req(instanceId, 0, PLDM_GET_FIRSTPART,
590 PLDM_BASE, request);
591 if (rc != PLDM_SUCCESS)
sampmisr6decfc12021-03-02 11:07:36 +0530592 {
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500593 std::cerr << "GetPLDMVersion encode failure. PLDM error code = "
594 << std::hex << std::showbase << rc << "\n";
595 requester.markFree(mctp_eid, instanceId);
sampmisr6decfc12021-03-02 11:07:36 +0530596 return;
597 }
598
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500599 auto getPLDMVersionHandler = [this](mctp_eid_t /*eid*/,
600 const pldm_msg* response,
601 size_t respMsgLen) {
602 if (response == nullptr || !respMsgLen)
sampmisr6decfc12021-03-02 11:07:36 +0530603 {
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500604 std::cerr << "Failed to receive response for "
605 << "getPLDMVersion command, Host seems to be off \n";
sampmisr6decfc12021-03-02 11:07:36 +0530606 return;
607 }
sampmisr6decfc12021-03-02 11:07:36 +0530608 std::cout << "Getting the response. PLDM RC = " << std::hex
609 << std::showbase
610 << static_cast<uint16_t>(response->payload[0]) << "\n";
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500611 this->responseReceived = true;
612 getHostPDR();
sampmisr6decfc12021-03-02 11:07:36 +0530613 };
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500614 rc = handler->registerRequest(mctp_eid, instanceId, PLDM_BASE,
615 PLDM_GET_PLDM_VERSION, std::move(requestMsg),
616 std::move(getPLDMVersionHandler));
617 if (rc)
sampmisr6decfc12021-03-02 11:07:36 +0530618 {
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500619 std::cerr << "Failed to discover Host state. Assuming Host as off \n";
sampmisr6decfc12021-03-02 11:07:36 +0530620 }
621}
622
623bool HostPDRHandler::isHostUp()
624{
625 return responseReceived;
626}
627
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530628void HostPDRHandler::setHostSensorState(const PDRList& stateSensorPDRs)
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600629{
630 for (const auto& stateSensorPDR : stateSensorPDRs)
631 {
632 auto pdr = reinterpret_cast<const pldm_state_sensor_pdr*>(
633 stateSensorPDR.data());
634
635 if (!pdr)
636 {
637 std::cerr << "Failed to get State sensor PDR" << std::endl;
638 pldm::utils::reportError(
639 "xyz.openbmc_project.bmc.pldm.InternalFailure");
640 return;
641 }
642
643 uint16_t sensorId = pdr->sensor_id;
644
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530645 for (const auto& [terminusHandle, terminusInfo] : tlPDRInfo)
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600646 {
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530647 if (terminusHandle == pdr->terminus_handle)
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600648 {
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530649 if (std::get<2>(terminusInfo) == PLDM_TL_PDR_VALID)
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600650 {
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530651 mctp_eid = std::get<1>(terminusInfo);
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600652 }
653
654 bitfield8_t sensorRearm;
655 sensorRearm.byte = 0;
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530656 uint8_t tid = std::get<0>(terminusInfo);
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600657
658 auto instanceId = requester.getInstanceId(mctp_eid);
659 std::vector<uint8_t> requestMsg(
660 sizeof(pldm_msg_hdr) +
661 PLDM_GET_STATE_SENSOR_READINGS_REQ_BYTES);
662 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
663 auto rc = encode_get_state_sensor_readings_req(
664 instanceId, sensorId, sensorRearm, 0, request);
665
666 if (rc != PLDM_SUCCESS)
667 {
668 requester.markFree(mctp_eid, instanceId);
669 std::cerr << "Failed to "
670 "encode_get_state_sensor_readings_req, rc = "
671 << rc << std::endl;
672 pldm::utils::reportError(
673 "xyz.openbmc_project.bmc.pldm.InternalFailure");
674 return;
675 }
676
677 auto getStateSensorReadingRespHandler = [=, this](
678 mctp_eid_t /*eid*/,
679 const pldm_msg*
680 response,
681 size_t respMsgLen) {
682 if (response == nullptr || !respMsgLen)
683 {
684 std::cerr << "Failed to receive response for "
685 "getStateSensorReading command \n";
686 return;
687 }
688 std::array<get_sensor_state_field, 8> stateField{};
689 uint8_t completionCode = 0;
690 uint8_t comp_sensor_count = 0;
691
692 auto rc = decode_get_state_sensor_readings_resp(
693 response, respMsgLen, &completionCode,
694 &comp_sensor_count, stateField.data());
695
696 if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS)
697 {
698 std::cerr
699 << "Failed to "
700 "decode_get_state_sensor_readings_resp, rc = "
701 << rc
702 << " cc=" << static_cast<unsigned>(completionCode)
703 << std::endl;
704 pldm::utils::reportError(
705 "xyz.openbmc_project.bmc.pldm.InternalFailure");
706 }
707
708 uint8_t eventState;
709 uint8_t previousEventState;
710 uint8_t sensorOffset = comp_sensor_count - 1;
711
712 for (size_t i = 0; i < comp_sensor_count; i++)
713 {
714 eventState = stateField[i].present_state;
715 previousEventState = stateField[i].previous_state;
716
717 emitStateSensorEventSignal(tid, sensorId, sensorOffset,
718 eventState,
719 previousEventState);
720
721 SensorEntry sensorEntry{tid, sensorId};
722
723 pldm::pdr::EntityInfo entityInfo{};
724 pldm::pdr::CompositeSensorStates
725 compositeSensorStates{};
726
727 try
728 {
729 std::tie(entityInfo, compositeSensorStates) =
730 lookupSensorInfo(sensorEntry);
731 }
732 catch (const std::out_of_range& e)
733 {
734 try
735 {
736 sensorEntry.terminusID = PLDM_TID_RESERVED;
737 std::tie(entityInfo, compositeSensorStates) =
738 lookupSensorInfo(sensorEntry);
739 }
740 catch (const std::out_of_range& e)
741 {
742 std::cerr << "No mapping for the events"
743 << std::endl;
744 }
745 }
746
747 if (sensorOffset > compositeSensorStates.size())
748 {
749 std::cerr
750 << " Error Invalid data, Invalid sensor offset"
751 << std::endl;
752 return;
753 }
754
755 const auto& possibleStates =
756 compositeSensorStates[sensorOffset];
757 if (possibleStates.find(eventState) ==
758 possibleStates.end())
759 {
760 std::cerr
761 << " Error invalid_data, Invalid event state"
762 << std::endl;
763 return;
764 }
765 const auto& [containerId, entityType, entityInstance] =
766 entityInfo;
767 pldm::responder::events::StateSensorEntry
768 stateSensorEntry{containerId, entityType,
769 entityInstance, sensorOffset};
770 handleStateSensorEvent(stateSensorEntry, eventState);
771 }
772 };
773
774 rc = handler->registerRequest(
775 mctp_eid, instanceId, PLDM_PLATFORM,
776 PLDM_GET_STATE_SENSOR_READINGS, std::move(requestMsg),
777 std::move(getStateSensorReadingRespHandler));
778
779 if (rc != PLDM_SUCCESS)
780 {
781 std::cerr << " Failed to send request to get State sensor "
782 "reading on Host "
783 << std::endl;
784 }
785 }
786 }
787 }
788}
Pavithra Barithaya51efaf82020-04-02 02:42:27 -0500789} // namespace pldm