blob: 1b0024c0fc30161437b33288a854f627ff5d292e [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>
Riya Dixit49cfb132023-03-02 04:26:53 -06009#include <phosphor-logging/lg2.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
Riya Dixit49cfb132023-03-02 04:26:53 -060017PHOSPHOR_LOG2_USING;
18
Pavithra Barithaya51efaf82020-04-02 02:42:27 -050019namespace pldm
20{
Brad Bishop5079ac42021-08-19 18:35:06 -040021using 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,
Andrew Jefferya330b2f2023-05-04 14:55:37 +093052 pldm_entity_association_tree* bmcEntityTree,
53 pldm::InstanceIdDb& instanceIdDb,
Tom Josephe5268cd2021-09-07 13:04:03 +053054 pldm::requester::Handler<pldm::requester::Request>* handler) :
Deepak Kodihalli87514cc2020-04-16 09:08:38 -050055 mctp_fd(mctp_fd),
Pavithra Barithaya3aec9972020-12-14 01:55:44 -060056 mctp_eid(mctp_eid), event(event), repo(repo),
57 stateSensorHandler(eventsJsonsDir), entityTree(entityTree),
Andrew Jefferya330b2f2023-05-04 14:55:37 +093058 bmcEntityTree(bmcEntityTree), instanceIdDb(instanceIdDb), handler(handler)
Deepak Kodihalli87514cc2020-04-16 09:08:38 -050059{
60 fs::path hostFruJson(fs::path(HOST_JSONS_DIR) / fruJson);
61 if (fs::exists(hostFruJson))
62 {
Pavithra Barithayae8beb892020-04-14 23:24:25 -050063 // Note parent entities for entities sent down by the host firmware.
64 // This will enable a merge of entity associations.
Deepak Kodihalli87514cc2020-04-16 09:08:38 -050065 try
66 {
67 std::ifstream jsonFile(hostFruJson);
68 auto data = Json::parse(jsonFile, nullptr, false);
69 if (data.is_discarded())
70 {
Riya Dixit49cfb132023-03-02 04:26:53 -060071 error("Parsing Host FRU json file failed");
Deepak Kodihalli87514cc2020-04-16 09:08:38 -050072 }
73 else
74 {
75 auto entities = data.value("entities", emptyJsonList);
76 for (auto& entity : entities)
77 {
78 EntityType entityType = entity.value("entity_type", 0);
79 auto parent = entity.value("parent", emptyJson);
80 pldm_entity p{};
81 p.entity_type = parent.value("entity_type", 0);
82 p.entity_instance_num = parent.value("entity_instance", 0);
83 parents.emplace(entityType, std::move(p));
84 }
85 }
86 }
87 catch (const std::exception& e)
88 {
Riya Dixit49cfb132023-03-02 04:26:53 -060089 error("Parsing Host FRU json file failed, exception = {ERR_EXCEP}",
90 "ERR_EXCEP", e.what());
Deepak Kodihalli87514cc2020-04-16 09:08:38 -050091 }
92 }
Deepak Kodihalli6b1d1ca2020-04-27 07:24:51 -050093
Patrick Williams84b790c2022-07-22 19:26:56 -050094 hostOffMatch = std::make_unique<sdbusplus::bus::match_t>(
Deepak Kodihalli6b1d1ca2020-04-27 07:24:51 -050095 pldm::utils::DBusHandler::getBus(),
96 propertiesChanged("/xyz/openbmc_project/state/host0",
97 "xyz.openbmc_project.State.Host"),
Patrick Williams84b790c2022-07-22 19:26:56 -050098 [this, repo, entityTree, bmcEntityTree](sdbusplus::message_t& msg) {
Patrick Williams6da4f912023-05-10 07:50:53 -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")
Deepak Kodihalli6b1d1ca2020-04-27 07:24:51 -0500108 {
Patrick Williams6da4f912023-05-10 07:50:53 -0500109 // Delete all the remote terminus information
110 std::erase_if(tlPDRInfo, [](const auto& item) {
111 auto const& [key, value] = item;
112 return key != TERMINUS_HANDLE;
113 });
114 pldm_pdr_remove_remote_pdrs(repo);
115 pldm_entity_association_tree_destroy_root(entityTree);
116 pldm_entity_association_tree_copy_root(bmcEntityTree,
117 entityTree);
118 this->sensorMap.clear();
119 this->responseReceived = false;
Deepak Kodihalli6b1d1ca2020-04-27 07:24:51 -0500120 }
Patrick Williams6da4f912023-05-10 07:50:53 -0500121 }
Deepak Kodihalli6b1d1ca2020-04-27 07:24:51 -0500122 });
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();
Pavithra Barithayaae5c97e2022-08-29 02:57:59 -0500128 modifiedPDRRecordHandles.clear();
129
130 if (isHostPdrModified)
131 {
132 modifiedPDRRecordHandles = std::move(recordHandles);
133 }
134 else
135 {
136 pdrRecordHandles = std::move(recordHandles);
137 }
Deepak Kodihalli8cb6f662020-04-10 02:55:43 -0500138
139 // Defer the actual fetch of PDRs from the host (by queuing the call on the
140 // main event loop). That way, we can respond to the platform event msg from
141 // the host firmware.
142 pdrFetchEvent = std::make_unique<sdeventplus::source::Defer>(
143 event, std::bind(std::mem_fn(&HostPDRHandler::_fetchPDR), this,
144 std::placeholders::_1));
145}
146
147void HostPDRHandler::_fetchPDR(sdeventplus::source::EventBase& /*source*/)
148{
Sampa Misrac0c79482021-06-02 08:01:54 -0500149 getHostPDR();
150}
151
152void HostPDRHandler::getHostPDR(uint32_t nextRecordHandle)
153{
Deepak Kodihalli8cb6f662020-04-10 02:55:43 -0500154 pdrFetchEvent.reset();
155
Pavithra Barithaya51efaf82020-04-02 02:42:27 -0500156 std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) +
157 PLDM_GET_PDR_REQ_BYTES);
158 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
Deepak Kodihalli7246e0c2020-07-08 06:40:18 -0500159 uint32_t recordHandle{};
Pavithra Barithayaae5c97e2022-08-29 02:57:59 -0500160 if (!nextRecordHandle && (!modifiedPDRRecordHandles.empty()) &&
161 isHostPdrModified)
Deepak Kodihalli7246e0c2020-07-08 06:40:18 -0500162 {
Pavithra Barithayaae5c97e2022-08-29 02:57:59 -0500163 recordHandle = modifiedPDRRecordHandles.front();
164 modifiedPDRRecordHandles.pop_front();
165 }
166 else if (!nextRecordHandle && (!pdrRecordHandles.empty()))
167 {
168 recordHandle = pdrRecordHandles.front();
169 pdrRecordHandles.pop_front();
Sampa Misrac0c79482021-06-02 08:01:54 -0500170 }
171 else
172 {
173 recordHandle = nextRecordHandle;
174 }
Andrew Jefferya330b2f2023-05-04 14:55:37 +0930175 auto instanceId = instanceIdDb.next(mctp_eid);
Sampa Misrac0c79482021-06-02 08:01:54 -0500176
Patrick Williams6da4f912023-05-10 07:50:53 -0500177 auto rc = encode_get_pdr_req(instanceId, recordHandle, 0,
178 PLDM_GET_FIRSTPART, UINT16_MAX, 0, request,
179 PLDM_GET_PDR_REQ_BYTES);
Sampa Misrac0c79482021-06-02 08:01:54 -0500180 if (rc != PLDM_SUCCESS)
181 {
Andrew Jefferya330b2f2023-05-04 14:55:37 +0930182 instanceIdDb.free(mctp_eid, instanceId);
Riya Dixit49cfb132023-03-02 04:26:53 -0600183 error("Failed to encode_get_pdr_req, rc = {RC}", "RC", rc);
Sampa Misrac0c79482021-06-02 08:01:54 -0500184 return;
185 }
Deepak Kodihalli7246e0c2020-07-08 06:40:18 -0500186
Sampa Misrac0c79482021-06-02 08:01:54 -0500187 rc = handler->registerRequest(
188 mctp_eid, instanceId, PLDM_PLATFORM, PLDM_GET_PDR,
189 std::move(requestMsg),
190 std::move(std::bind_front(&HostPDRHandler::processHostPDRs, this)));
191 if (rc)
Pavithra Barithaya51efaf82020-04-02 02:42:27 -0500192 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600193 error("Failed to send the GetPDR request to Host");
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500194 }
Pavithra Barithaya51efaf82020-04-02 02:42:27 -0500195}
196
Pavithra Barithaya3aec9972020-12-14 01:55:44 -0600197int HostPDRHandler::handleStateSensorEvent(const StateSensorEntry& entry,
198 pdr::EventState state)
199{
200 auto rc = stateSensorHandler.eventAction(entry, state);
201 if (rc != PLDM_SUCCESS)
202 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600203 error("Failed to fetch and update D-bus property, rc = {RC}", "RC", rc);
Pavithra Barithaya3aec9972020-12-14 01:55:44 -0600204 return rc;
205 }
206 return PLDM_SUCCESS;
207}
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500208bool HostPDRHandler::getParent(EntityType type, pldm_entity& parent)
209{
210 auto found = parents.find(type);
211 if (found != parents.end())
212 {
213 parent.entity_type = found->second.entity_type;
214 parent.entity_instance_num = found->second.entity_instance_num;
215 return true;
216 }
217
218 return false;
219}
220
221void HostPDRHandler::mergeEntityAssociations(const std::vector<uint8_t>& pdr)
222{
223 size_t numEntities{};
224 pldm_entity* entities = nullptr;
225 bool merged = false;
226 auto entityPdr = reinterpret_cast<pldm_pdr_entity_association*>(
227 const_cast<uint8_t*>(pdr.data()) + sizeof(pldm_pdr_hdr));
228
229 pldm_entity_association_pdr_extract(pdr.data(), pdr.size(), &numEntities,
230 &entities);
231 for (size_t i = 0; i < numEntities; ++i)
232 {
233 pldm_entity parent{};
234 if (getParent(entities[i].entity_type, parent))
235 {
236 auto node = pldm_entity_association_tree_find(entityTree, &parent);
237 if (node)
238 {
George Liu64a8f0f2021-06-12 10:56:11 +0800239 pldm_entity_association_tree_add(entityTree, &entities[i],
240 0xFFFF, node,
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500241 entityPdr->association_type);
242 merged = true;
243 }
244 }
245 }
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500246
247 if (merged)
248 {
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500249 // Update our PDR repo with the merged entity association PDRs
Sampa Misra719ed392021-06-04 05:15:13 -0500250 pldm_entity_node* node = nullptr;
251 pldm_find_entity_ref_in_tree(entityTree, entities[0], &node);
252 if (node == nullptr)
253 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600254 error("could not find referrence of the entity in the tree");
Sampa Misra719ed392021-06-04 05:15:13 -0500255 }
256 else
257 {
Manojkiran Eda3ca40452021-10-04 22:51:37 +0530258 pldm_entity_association_pdr_add_from_node(
259 node, repo, &entities, numEntities, true, TERMINUS_HANDLE);
Sampa Misra719ed392021-06-04 05:15:13 -0500260 }
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500261 }
Sampa Misra719ed392021-06-04 05:15:13 -0500262 free(entities);
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500263}
264
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500265void HostPDRHandler::sendPDRRepositoryChgEvent(std::vector<uint8_t>&& pdrTypes,
266 uint8_t eventDataFormat)
267{
268 assert(eventDataFormat == FORMAT_IS_PDR_HANDLES);
269
270 // Extract from the PDR repo record handles of PDRs we want the host
271 // to pull up.
272 std::vector<uint8_t> eventDataOps{PLDM_RECORDS_ADDED};
273 std::vector<uint8_t> numsOfChangeEntries(1);
274 std::vector<std::vector<ChangeEntry>> changeEntries(
275 numsOfChangeEntries.size());
276 for (auto pdrType : pdrTypes)
277 {
278 const pldm_pdr_record* record{};
279 do
280 {
281 record = pldm_pdr_find_record_by_type(repo, pdrType, record,
282 nullptr, nullptr);
283 if (record && pldm_pdr_record_is_remote(record))
284 {
285 changeEntries[0].push_back(
286 pldm_pdr_get_record_handle(repo, record));
287 }
288 } while (record);
289 }
290 if (changeEntries.empty())
291 {
292 return;
293 }
294 numsOfChangeEntries[0] = changeEntries[0].size();
295
296 // Encode PLDM platform event msg to indicate a PDR repo change.
297 size_t maxSize = PLDM_PDR_REPOSITORY_CHG_EVENT_MIN_LENGTH +
298 PLDM_PDR_REPOSITORY_CHANGE_RECORD_MIN_LENGTH +
299 changeEntries[0].size() * sizeof(uint32_t);
300 std::vector<uint8_t> eventDataVec{};
301 eventDataVec.resize(maxSize);
302 auto eventData =
303 reinterpret_cast<struct pldm_pdr_repository_chg_event_data*>(
304 eventDataVec.data());
305 size_t actualSize{};
306 auto firstEntry = changeEntries[0].data();
307 auto rc = encode_pldm_pdr_repository_chg_event_data(
308 eventDataFormat, 1, eventDataOps.data(), numsOfChangeEntries.data(),
309 &firstEntry, eventData, &actualSize, maxSize);
310 if (rc != PLDM_SUCCESS)
311 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600312 error("Failed to encode_pldm_pdr_repository_chg_event_data, rc = {RC}",
313 "RC", rc);
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500314 return;
315 }
Andrew Jefferya330b2f2023-05-04 14:55:37 +0930316 auto instanceId = instanceIdDb.next(mctp_eid);
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500317 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(
ArchanaKakani6c39c7a2022-12-05 04:36:35 -0600322 instanceId, 1, TERMINUS_ID, PLDM_PDR_REPOSITORY_CHG_EVENT,
323 eventDataVec.data(), actualSize, request,
Christian Geddes3bdb3c22020-05-01 14:55:39 -0500324 actualSize + PLDM_PLATFORM_EVENT_MESSAGE_MIN_REQ_BYTES);
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500325 if (rc != PLDM_SUCCESS)
326 {
Andrew Jefferya330b2f2023-05-04 14:55:37 +0930327 instanceIdDb.free(mctp_eid, instanceId);
Riya Dixit49cfb132023-03-02 04:26:53 -0600328 error("Failed to encode_platform_event_message_req, rc = {RC}", "RC",
329 rc);
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500330 return;
331 }
332
Patrick Williams6da4f912023-05-10 07:50:53 -0500333 auto platformEventMessageResponseHandler =
334 [](mctp_eid_t /*eid*/, const pldm_msg* response, size_t respMsgLen) {
Tom Joseph74f27c72021-05-16 07:58:53 -0700335 if (response == nullptr || !respMsgLen)
336 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600337 error(
338 "Failed to receive response for the PDR repository changed event");
Tom Joseph74f27c72021-05-16 07:58:53 -0700339 return;
340 }
341
342 uint8_t completionCode{};
343 uint8_t status{};
344 auto responsePtr = reinterpret_cast<const struct pldm_msg*>(response);
Pavithra Barithaya54b5a562021-09-27 06:07:10 -0500345 auto rc = decode_platform_event_message_resp(responsePtr, respMsgLen,
346 &completionCode, &status);
Sampa Misrac0c79482021-06-02 08:01:54 -0500347 if (rc || completionCode)
Tom Joseph74f27c72021-05-16 07:58:53 -0700348 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600349 error(
350 "Failed to decode_platform_event_message_resp: {RC}, cc = {CC}",
351 "RC", rc, "CC", static_cast<unsigned>(completionCode));
Tom Joseph74f27c72021-05-16 07:58:53 -0700352 }
353 };
354
Sampa Misrac0c79482021-06-02 08:01:54 -0500355 rc = handler->registerRequest(
Sampa Misra626c5652021-08-11 10:28:48 -0500356 mctp_eid, instanceId, PLDM_PLATFORM, PLDM_PLATFORM_EVENT_MESSAGE,
Tom Joseph74f27c72021-05-16 07:58:53 -0700357 std::move(requestMsg), std::move(platformEventMessageResponseHandler));
Sampa Misrac0c79482021-06-02 08:01:54 -0500358 if (rc)
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500359 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600360 error("Failed to send the PDR repository changed event request");
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500361 }
362}
363
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530364void HostPDRHandler::parseStateSensorPDRs(const PDRList& stateSensorPDRs)
Sampa Misra868c8792020-05-26 03:12:13 -0500365{
366 for (const auto& pdr : stateSensorPDRs)
367 {
368 SensorEntry sensorEntry{};
369 const auto& [terminusHandle, sensorID, sensorInfo] =
370 responder::pdr_utils::parseStateSensorPDR(pdr);
371 sensorEntry.sensorID = sensorID;
372 try
373 {
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530374 sensorEntry.terminusID = std::get<0>(tlPDRInfo.at(terminusHandle));
Sampa Misra868c8792020-05-26 03:12:13 -0500375 }
376 // If there is no mapping for terminusHandle assign the reserved TID
377 // value of 0xFF to indicate that.
378 catch (const std::out_of_range& e)
379 {
380 sensorEntry.terminusID = PLDM_TID_RESERVED;
381 }
382 sensorMap.emplace(sensorEntry, std::move(sensorInfo));
383 }
384}
385
Sampa Misrac0c79482021-06-02 08:01:54 -0500386void HostPDRHandler::processHostPDRs(mctp_eid_t /*eid*/,
387 const pldm_msg* response,
388 size_t respMsgLen)
389{
390 static bool merged = false;
391 static PDRList stateSensorPDRs{};
Sampa Misrac0c79482021-06-02 08:01:54 -0500392 uint32_t nextRecordHandle{};
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600393 uint8_t tlEid = 0;
394 bool tlValid = true;
395 uint32_t rh = 0;
396 uint16_t terminusHandle = 0;
Manojkiran Eda3ca40452021-10-04 22:51:37 +0530397 uint16_t pdrTerminusHandle = 0;
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600398 uint8_t tid = 0;
399
Sampa Misrac0c79482021-06-02 08:01:54 -0500400 uint8_t completionCode{};
401 uint32_t nextDataTransferHandle{};
402 uint8_t transferFlag{};
403 uint16_t respCount{};
404 uint8_t transferCRC{};
405 if (response == nullptr || !respMsgLen)
406 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600407 error("Failed to receive response for the GetPDR command");
Sampa Misrac0c79482021-06-02 08:01:54 -0500408 return;
409 }
410
411 auto rc = decode_get_pdr_resp(
412 response, respMsgLen /*- sizeof(pldm_msg_hdr)*/, &completionCode,
413 &nextRecordHandle, &nextDataTransferHandle, &transferFlag, &respCount,
414 nullptr, 0, &transferCRC);
415 std::vector<uint8_t> responsePDRMsg;
416 responsePDRMsg.resize(respMsgLen + sizeof(pldm_msg_hdr));
417 memcpy(responsePDRMsg.data(), response, respMsgLen + sizeof(pldm_msg_hdr));
Sampa Misrac0c79482021-06-02 08:01:54 -0500418 if (rc != PLDM_SUCCESS)
419 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600420 error("Failed to decode_get_pdr_resp, rc = {RC}", "RC", rc);
Sampa Misrac0c79482021-06-02 08:01:54 -0500421 return;
422 }
423 else
424 {
425 std::vector<uint8_t> pdr(respCount, 0);
426 rc = decode_get_pdr_resp(response, respMsgLen, &completionCode,
427 &nextRecordHandle, &nextDataTransferHandle,
428 &transferFlag, &respCount, pdr.data(),
429 respCount, &transferCRC);
430 if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS)
431 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600432 error("Failed to decode_get_pdr_resp: rc = {RC}, cc = {CC}", "RC",
433 rc, "CC", static_cast<unsigned>(completionCode));
Sampa Misrac0c79482021-06-02 08:01:54 -0500434 return;
435 }
436 else
437 {
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600438 // when nextRecordHandle is 0, we need the recordHandle of the last
439 // PDR and not 0-1.
440 if (!nextRecordHandle)
441 {
442 rh = nextRecordHandle;
443 }
444 else
445 {
446 rh = nextRecordHandle - 1;
447 }
448
Sampa Misrac0c79482021-06-02 08:01:54 -0500449 auto pdrHdr = reinterpret_cast<pldm_pdr_hdr*>(pdr.data());
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600450 if (!rh)
451 {
452 rh = pdrHdr->record_handle;
453 }
454
Sampa Misrac0c79482021-06-02 08:01:54 -0500455 if (pdrHdr->type == PLDM_PDR_ENTITY_ASSOCIATION)
456 {
457 this->mergeEntityAssociations(pdr);
458 merged = true;
459 }
460 else
461 {
462 if (pdrHdr->type == PLDM_TERMINUS_LOCATOR_PDR)
463 {
Manojkiran Eda3ca40452021-10-04 22:51:37 +0530464 pdrTerminusHandle =
465 extractTerminusHandle<pldm_terminus_locator_pdr>(pdr);
Sampa Misrac0c79482021-06-02 08:01:54 -0500466 auto tlpdr =
467 reinterpret_cast<const pldm_terminus_locator_pdr*>(
468 pdr.data());
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600469
470 terminusHandle = tlpdr->terminus_handle;
471 tid = tlpdr->tid;
472 auto terminus_locator_type = tlpdr->terminus_locator_type;
473 if (terminus_locator_type ==
474 PLDM_TERMINUS_LOCATOR_TYPE_MCTP_EID)
475 {
476 auto locatorValue = reinterpret_cast<
477 const pldm_terminus_locator_type_mctp_eid*>(
478 tlpdr->terminus_locator_value);
479 tlEid = static_cast<uint8_t>(locatorValue->eid);
480 }
481 if (tlpdr->validity == 0)
482 {
483 tlValid = false;
484 }
Pavithra Barithaya52aad392022-08-02 04:18:52 -0500485 for (const auto& terminusMap : tlPDRInfo)
486 {
487 if ((terminusHandle == (terminusMap.first)) &&
488 (get<1>(terminusMap.second) == tlEid) &&
489 (get<2>(terminusMap.second) == tlpdr->validity))
490 {
491 // TL PDR already present with same validity don't
492 // add the PDR to the repo just return
493 return;
494 }
495 }
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530496 tlPDRInfo.insert_or_assign(
497 tlpdr->terminus_handle,
498 std::make_tuple(tlpdr->tid, tlEid, tlpdr->validity));
Sampa Misrac0c79482021-06-02 08:01:54 -0500499 }
500 else if (pdrHdr->type == PLDM_STATE_SENSOR_PDR)
501 {
Manojkiran Eda3ca40452021-10-04 22:51:37 +0530502 pdrTerminusHandle =
503 extractTerminusHandle<pldm_state_sensor_pdr>(pdr);
Sampa Misrac0c79482021-06-02 08:01:54 -0500504 stateSensorPDRs.emplace_back(pdr);
505 }
Manojkiran Eda3ca40452021-10-04 22:51:37 +0530506 else if (pdrHdr->type == PLDM_PDR_FRU_RECORD_SET)
507 {
508 pdrTerminusHandle =
509 extractTerminusHandle<pldm_pdr_fru_record_set>(pdr);
510 }
511 else if (pdrHdr->type == PLDM_STATE_EFFECTER_PDR)
512 {
513 pdrTerminusHandle =
514 extractTerminusHandle<pldm_state_effecter_pdr>(pdr);
515 }
516 else if (pdrHdr->type == PLDM_NUMERIC_EFFECTER_PDR)
517 {
518 pdrTerminusHandle =
519 extractTerminusHandle<pldm_numeric_effecter_value_pdr>(
520 pdr);
521 }
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600522 // if the TLPDR is invalid update the repo accordingly
523 if (!tlValid)
524 {
525 pldm_pdr_update_TL_pdr(repo, terminusHandle, tid, tlEid,
526 tlValid);
527 }
528 else
529 {
Manojkiran Eda3ca40452021-10-04 22:51:37 +0530530 pldm_pdr_add(repo, pdr.data(), respCount, rh, true,
531 pdrTerminusHandle);
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600532 }
Sampa Misrac0c79482021-06-02 08:01:54 -0500533 }
534 }
535 }
536 if (!nextRecordHandle)
537 {
538 /*received last record*/
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530539 this->parseStateSensorPDRs(stateSensorPDRs);
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600540 if (isHostUp())
541 {
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530542 this->setHostSensorState(stateSensorPDRs);
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600543 }
Sampa Misrac0c79482021-06-02 08:01:54 -0500544 stateSensorPDRs.clear();
Sampa Misrac0c79482021-06-02 08:01:54 -0500545 if (merged)
546 {
547 merged = false;
548 deferredPDRRepoChgEvent =
549 std::make_unique<sdeventplus::source::Defer>(
550 event,
551 std::bind(
552 std::mem_fn((&HostPDRHandler::_processPDRRepoChgEvent)),
553 this, std::placeholders::_1));
554 }
555 }
556 else
557 {
Pavithra Barithayaae5c97e2022-08-29 02:57:59 -0500558 if (modifiedPDRRecordHandles.empty() && isHostPdrModified)
559 {
560 isHostPdrModified = false;
561 }
562 else
563 {
564 deferredFetchPDREvent =
565 std::make_unique<sdeventplus::source::Defer>(
566 event,
567 std::bind(
568 std::mem_fn((&HostPDRHandler::_processFetchPDREvent)),
569 this, nextRecordHandle, std::placeholders::_1));
570 }
Sampa Misrac0c79482021-06-02 08:01:54 -0500571 }
572}
573
574void HostPDRHandler::_processPDRRepoChgEvent(
575 sdeventplus::source::EventBase& /*source */)
576{
577 deferredPDRRepoChgEvent.reset();
578 this->sendPDRRepositoryChgEvent(
579 std::move(std::vector<uint8_t>(1, PLDM_PDR_ENTITY_ASSOCIATION)),
580 FORMAT_IS_PDR_HANDLES);
581}
582
583void HostPDRHandler::_processFetchPDREvent(
584 uint32_t nextRecordHandle, sdeventplus::source::EventBase& /*source */)
585{
586 deferredFetchPDREvent.reset();
587 if (!this->pdrRecordHandles.empty())
588 {
589 nextRecordHandle = this->pdrRecordHandles.front();
590 this->pdrRecordHandles.pop_front();
591 }
Pavithra Barithayaae5c97e2022-08-29 02:57:59 -0500592 if (isHostPdrModified && (!this->modifiedPDRRecordHandles.empty()))
593 {
594 nextRecordHandle = this->modifiedPDRRecordHandles.front();
595 this->modifiedPDRRecordHandles.pop_front();
596 }
Sampa Misrac0c79482021-06-02 08:01:54 -0500597 this->getHostPDR(nextRecordHandle);
598}
599
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500600void HostPDRHandler::setHostFirmwareCondition()
sampmisr6decfc12021-03-02 11:07:36 +0530601{
sampmisr6decfc12021-03-02 11:07:36 +0530602 responseReceived = false;
Andrew Jefferya330b2f2023-05-04 14:55:37 +0930603 auto instanceId = instanceIdDb.next(mctp_eid);
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500604 std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) +
605 PLDM_GET_VERSION_REQ_BYTES);
606 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
607 auto rc = encode_get_version_req(instanceId, 0, PLDM_GET_FIRSTPART,
608 PLDM_BASE, request);
609 if (rc != PLDM_SUCCESS)
sampmisr6decfc12021-03-02 11:07:36 +0530610 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600611 error("GetPLDMVersion encode failure. PLDM error code = {RC}", "RC",
612 lg2::hex, rc);
Andrew Jefferya330b2f2023-05-04 14:55:37 +0930613 instanceIdDb.free(mctp_eid, instanceId);
sampmisr6decfc12021-03-02 11:07:36 +0530614 return;
615 }
616
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500617 auto getPLDMVersionHandler = [this](mctp_eid_t /*eid*/,
618 const pldm_msg* response,
619 size_t respMsgLen) {
620 if (response == nullptr || !respMsgLen)
sampmisr6decfc12021-03-02 11:07:36 +0530621 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600622 error(
623 "Failed to receive response for getPLDMVersion command, Host seems to be off");
sampmisr6decfc12021-03-02 11:07:36 +0530624 return;
625 }
Riya Dixit49cfb132023-03-02 04:26:53 -0600626 info("Getting the response. PLDM RC = {RC}", "RC", lg2::hex,
627 static_cast<uint16_t>(response->payload[0]));
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500628 this->responseReceived = true;
629 getHostPDR();
sampmisr6decfc12021-03-02 11:07:36 +0530630 };
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500631 rc = handler->registerRequest(mctp_eid, instanceId, PLDM_BASE,
632 PLDM_GET_PLDM_VERSION, std::move(requestMsg),
633 std::move(getPLDMVersionHandler));
634 if (rc)
sampmisr6decfc12021-03-02 11:07:36 +0530635 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600636 error("Failed to discover Host state. Assuming Host as off");
sampmisr6decfc12021-03-02 11:07:36 +0530637 }
638}
639
640bool HostPDRHandler::isHostUp()
641{
642 return responseReceived;
643}
644
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530645void HostPDRHandler::setHostSensorState(const PDRList& stateSensorPDRs)
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600646{
647 for (const auto& stateSensorPDR : stateSensorPDRs)
648 {
649 auto pdr = reinterpret_cast<const pldm_state_sensor_pdr*>(
650 stateSensorPDR.data());
651
652 if (!pdr)
653 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600654 error("Failed to get State sensor PDR");
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600655 pldm::utils::reportError(
656 "xyz.openbmc_project.bmc.pldm.InternalFailure");
657 return;
658 }
659
660 uint16_t sensorId = pdr->sensor_id;
661
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530662 for (const auto& [terminusHandle, terminusInfo] : tlPDRInfo)
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600663 {
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530664 if (terminusHandle == pdr->terminus_handle)
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600665 {
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530666 if (std::get<2>(terminusInfo) == PLDM_TL_PDR_VALID)
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600667 {
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530668 mctp_eid = std::get<1>(terminusInfo);
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600669 }
670
671 bitfield8_t sensorRearm;
672 sensorRearm.byte = 0;
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530673 uint8_t tid = std::get<0>(terminusInfo);
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600674
Andrew Jefferya330b2f2023-05-04 14:55:37 +0930675 auto instanceId = instanceIdDb.next(mctp_eid);
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600676 std::vector<uint8_t> requestMsg(
677 sizeof(pldm_msg_hdr) +
678 PLDM_GET_STATE_SENSOR_READINGS_REQ_BYTES);
679 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
680 auto rc = encode_get_state_sensor_readings_req(
681 instanceId, sensorId, sensorRearm, 0, request);
682
683 if (rc != PLDM_SUCCESS)
684 {
Andrew Jefferya330b2f2023-05-04 14:55:37 +0930685 instanceIdDb.free(mctp_eid, instanceId);
Riya Dixit49cfb132023-03-02 04:26:53 -0600686 error(
687 "Failed to encode_get_state_sensor_readings_req, rc = {RC}",
688 "RC", rc);
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600689 pldm::utils::reportError(
690 "xyz.openbmc_project.bmc.pldm.InternalFailure");
691 return;
692 }
693
Patrick Williams6da4f912023-05-10 07:50:53 -0500694 auto getStateSensorReadingRespHandler =
695 [=, this](mctp_eid_t /*eid*/, const pldm_msg* response,
696 size_t respMsgLen) {
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600697 if (response == nullptr || !respMsgLen)
698 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600699 error(
700 "Failed to receive response for getStateSensorReading command");
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600701 return;
702 }
703 std::array<get_sensor_state_field, 8> stateField{};
704 uint8_t completionCode = 0;
705 uint8_t comp_sensor_count = 0;
706
707 auto rc = decode_get_state_sensor_readings_resp(
708 response, respMsgLen, &completionCode,
709 &comp_sensor_count, stateField.data());
710
711 if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS)
712 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600713 error(
714 "Failed to decode_get_state_sensor_readings_resp, rc = {RC} cc = {CC}",
715 "RC", rc, "CC",
716 static_cast<unsigned>(completionCode));
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600717 pldm::utils::reportError(
718 "xyz.openbmc_project.bmc.pldm.InternalFailure");
719 }
720
721 uint8_t eventState;
722 uint8_t previousEventState;
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600723
RIYA DIXITbb5fda42022-09-27 06:48:08 -0500724 for (uint8_t sensorOffset = 0;
725 sensorOffset < comp_sensor_count; sensorOffset++)
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600726 {
RIYA DIXITbb5fda42022-09-27 06:48:08 -0500727 eventState = stateField[sensorOffset].present_state;
728 previousEventState =
729 stateField[sensorOffset].previous_state;
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600730
731 emitStateSensorEventSignal(tid, sensorId, sensorOffset,
732 eventState,
733 previousEventState);
734
735 SensorEntry sensorEntry{tid, sensorId};
736
737 pldm::pdr::EntityInfo entityInfo{};
738 pldm::pdr::CompositeSensorStates
739 compositeSensorStates{};
740
741 try
742 {
743 std::tie(entityInfo, compositeSensorStates) =
744 lookupSensorInfo(sensorEntry);
745 }
746 catch (const std::out_of_range& e)
747 {
748 try
749 {
750 sensorEntry.terminusID = PLDM_TID_RESERVED;
751 std::tie(entityInfo, compositeSensorStates) =
752 lookupSensorInfo(sensorEntry);
753 }
754 catch (const std::out_of_range& e)
755 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600756 error("No mapping for the events");
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600757 }
758 }
759
760 if (sensorOffset > compositeSensorStates.size())
761 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600762 error("Error Invalid data, Invalid sensor offset");
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600763 return;
764 }
765
766 const auto& possibleStates =
767 compositeSensorStates[sensorOffset];
768 if (possibleStates.find(eventState) ==
769 possibleStates.end())
770 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600771 error("Error invalid_data, Invalid event state");
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600772 return;
773 }
Patrick Williams6da4f912023-05-10 07:50:53 -0500774 const auto& [containerId, entityType,
775 entityInstance] = entityInfo;
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600776 pldm::responder::events::StateSensorEntry
777 stateSensorEntry{containerId, entityType,
778 entityInstance, sensorOffset};
779 handleStateSensorEvent(stateSensorEntry, eventState);
780 }
781 };
782
783 rc = handler->registerRequest(
784 mctp_eid, instanceId, PLDM_PLATFORM,
785 PLDM_GET_STATE_SENSOR_READINGS, std::move(requestMsg),
786 std::move(getStateSensorReadingRespHandler));
787
788 if (rc != PLDM_SUCCESS)
789 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600790 error(
791 "Failed to send request to get State sensor reading on Host");
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600792 }
793 }
794 }
795 }
796}
Pavithra Barithaya51efaf82020-04-02 02:42:27 -0500797} // namespace pldm