blob: bcd3928090f82b92d0d144bd3552db427c8d3b61 [file] [log] [blame]
Pavithra Barithaya51efaf82020-04-02 02:42:27 -05001#include "host_pdr_handler.hpp"
2
Pavithra Barithayae8beb892020-04-14 23:24:25 -05003#include <assert.h>
George Liuc453e162022-12-21 17:16:23 +08004#include <libpldm/pldm.h>
Pavithra Barithayae8beb892020-04-14 23:24:25 -05005
Deepak Kodihalli87514cc2020-04-16 09:08:38 -05006#include <nlohmann/json.hpp>
Riya Dixit49cfb132023-03-02 04:26:53 -06007#include <phosphor-logging/lg2.hpp>
sampmisr6decfc12021-03-02 11:07:36 +05308#include <sdeventplus/clock.hpp>
9#include <sdeventplus/exception.hpp>
10#include <sdeventplus/source/io.hpp>
11#include <sdeventplus/source/time.hpp>
Deepak Kodihalli87514cc2020-04-16 09:08:38 -050012
George Liu6492f522020-06-16 10:34:05 +080013#include <fstream>
Pavithra Barithaya51efaf82020-04-02 02:42:27 -050014
Riya Dixit49cfb132023-03-02 04:26:53 -060015PHOSPHOR_LOG2_USING;
16
Pavithra Barithaya51efaf82020-04-02 02:42:27 -050017namespace pldm
18{
Brad Bishop5079ac42021-08-19 18:35:06 -040019using 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,
Andrew Jefferya330b2f2023-05-04 14:55:37 +093050 pldm_entity_association_tree* bmcEntityTree,
51 pldm::InstanceIdDb& instanceIdDb,
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),
Andrew Jefferya330b2f2023-05-04 14:55:37 +093056 bmcEntityTree(bmcEntityTree), instanceIdDb(instanceIdDb), 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 {
Riya Dixit49cfb132023-03-02 04:26:53 -060069 error("Parsing Host FRU json file failed");
Deepak Kodihalli87514cc2020-04-16 09:08:38 -050070 }
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 {
Riya Dixit49cfb132023-03-02 04:26:53 -060087 error("Parsing Host FRU json file failed, exception = {ERR_EXCEP}",
88 "ERR_EXCEP", e.what());
Deepak Kodihalli87514cc2020-04-16 09:08:38 -050089 }
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) {
Patrick Williams6da4f912023-05-10 07:50:53 -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")
Deepak Kodihalli6b1d1ca2020-04-27 07:24:51 -0500106 {
Patrick Williams6da4f912023-05-10 07:50:53 -0500107 // Delete all the remote terminus information
108 std::erase_if(tlPDRInfo, [](const auto& item) {
109 auto const& [key, value] = item;
110 return key != TERMINUS_HANDLE;
111 });
112 pldm_pdr_remove_remote_pdrs(repo);
113 pldm_entity_association_tree_destroy_root(entityTree);
114 pldm_entity_association_tree_copy_root(bmcEntityTree,
115 entityTree);
116 this->sensorMap.clear();
117 this->responseReceived = false;
Deepak Kodihalli6b1d1ca2020-04-27 07:24:51 -0500118 }
Patrick Williams6da4f912023-05-10 07:50:53 -0500119 }
Deepak Kodihalli6b1d1ca2020-04-27 07:24:51 -0500120 });
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();
Pavithra Barithayaae5c97e2022-08-29 02:57:59 -0500126 modifiedPDRRecordHandles.clear();
127
128 if (isHostPdrModified)
129 {
130 modifiedPDRRecordHandles = std::move(recordHandles);
131 }
132 else
133 {
134 pdrRecordHandles = std::move(recordHandles);
135 }
Deepak Kodihalli8cb6f662020-04-10 02:55:43 -0500136
137 // Defer the actual fetch of PDRs from the host (by queuing the call on the
138 // main event loop). That way, we can respond to the platform event msg from
139 // the host firmware.
140 pdrFetchEvent = std::make_unique<sdeventplus::source::Defer>(
141 event, std::bind(std::mem_fn(&HostPDRHandler::_fetchPDR), this,
142 std::placeholders::_1));
143}
144
145void HostPDRHandler::_fetchPDR(sdeventplus::source::EventBase& /*source*/)
146{
Sampa Misrac0c79482021-06-02 08:01:54 -0500147 getHostPDR();
148}
149
150void HostPDRHandler::getHostPDR(uint32_t nextRecordHandle)
151{
Deepak Kodihalli8cb6f662020-04-10 02:55:43 -0500152 pdrFetchEvent.reset();
153
Pavithra Barithaya51efaf82020-04-02 02:42:27 -0500154 std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) +
155 PLDM_GET_PDR_REQ_BYTES);
156 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
Deepak Kodihalli7246e0c2020-07-08 06:40:18 -0500157 uint32_t recordHandle{};
Pavithra Barithayaae5c97e2022-08-29 02:57:59 -0500158 if (!nextRecordHandle && (!modifiedPDRRecordHandles.empty()) &&
159 isHostPdrModified)
Deepak Kodihalli7246e0c2020-07-08 06:40:18 -0500160 {
Pavithra Barithayaae5c97e2022-08-29 02:57:59 -0500161 recordHandle = modifiedPDRRecordHandles.front();
162 modifiedPDRRecordHandles.pop_front();
163 }
164 else if (!nextRecordHandle && (!pdrRecordHandles.empty()))
165 {
166 recordHandle = pdrRecordHandles.front();
167 pdrRecordHandles.pop_front();
Sampa Misrac0c79482021-06-02 08:01:54 -0500168 }
169 else
170 {
171 recordHandle = nextRecordHandle;
172 }
Andrew Jefferya330b2f2023-05-04 14:55:37 +0930173 auto instanceId = instanceIdDb.next(mctp_eid);
Sampa Misrac0c79482021-06-02 08:01:54 -0500174
Patrick Williams6da4f912023-05-10 07:50:53 -0500175 auto rc = encode_get_pdr_req(instanceId, recordHandle, 0,
176 PLDM_GET_FIRSTPART, UINT16_MAX, 0, request,
177 PLDM_GET_PDR_REQ_BYTES);
Sampa Misrac0c79482021-06-02 08:01:54 -0500178 if (rc != PLDM_SUCCESS)
179 {
Andrew Jefferya330b2f2023-05-04 14:55:37 +0930180 instanceIdDb.free(mctp_eid, instanceId);
Riya Dixit49cfb132023-03-02 04:26:53 -0600181 error("Failed to encode_get_pdr_req, rc = {RC}", "RC", rc);
Sampa Misrac0c79482021-06-02 08:01:54 -0500182 return;
183 }
Deepak Kodihalli7246e0c2020-07-08 06:40:18 -0500184
Sampa Misrac0c79482021-06-02 08:01:54 -0500185 rc = handler->registerRequest(
186 mctp_eid, instanceId, PLDM_PLATFORM, PLDM_GET_PDR,
187 std::move(requestMsg),
188 std::move(std::bind_front(&HostPDRHandler::processHostPDRs, this)));
189 if (rc)
Pavithra Barithaya51efaf82020-04-02 02:42:27 -0500190 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600191 error("Failed to send the GetPDR request to Host");
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500192 }
Pavithra Barithaya51efaf82020-04-02 02:42:27 -0500193}
194
Pavithra Barithaya3aec9972020-12-14 01:55:44 -0600195int HostPDRHandler::handleStateSensorEvent(const StateSensorEntry& entry,
196 pdr::EventState state)
197{
198 auto rc = stateSensorHandler.eventAction(entry, state);
199 if (rc != PLDM_SUCCESS)
200 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600201 error("Failed to fetch and update D-bus property, rc = {RC}", "RC", rc);
Pavithra Barithaya3aec9972020-12-14 01:55:44 -0600202 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 {
Manojkiran Eda8e715ae2021-07-04 21:46:43 +0530234 auto node = pldm_entity_association_tree_find_with_locality(
235 entityTree, &parent, true);
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500236 if (node)
237 {
Manojkiran Eda8e715ae2021-07-04 21:46:43 +0530238 pldm_entity_association_tree_add_entity(
239 entityTree, &entities[i], 0xFFFF, node,
240 entityPdr->association_type, false, true, 0xFFFF);
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500241 merged = true;
242 }
243 }
244 }
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500245
246 if (merged)
247 {
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500248 // Update our PDR repo with the merged entity association PDRs
Sampa Misra719ed392021-06-04 05:15:13 -0500249 pldm_entity_node* node = nullptr;
250 pldm_find_entity_ref_in_tree(entityTree, entities[0], &node);
251 if (node == nullptr)
252 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600253 error("could not find referrence of the entity in the tree");
Sampa Misra719ed392021-06-04 05:15:13 -0500254 }
255 else
256 {
Andrew Jeffery1fd3c512023-07-03 13:02:03 +0930257 int rc = pldm_entity_association_pdr_add_from_node_check(
Manojkiran Eda3ca40452021-10-04 22:51:37 +0530258 node, repo, &entities, numEntities, true, TERMINUS_HANDLE);
Andrew Jeffery1fd3c512023-07-03 13:02:03 +0930259 if (rc)
260 {
261 error(
262 "Failed to add entity association PDR from node: {LIBPLDM_ERROR}",
263 "LIBPLDM_ERROR", rc);
264 }
Sampa Misra719ed392021-06-04 05:15:13 -0500265 }
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500266 }
Sampa Misra719ed392021-06-04 05:15:13 -0500267 free(entities);
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500268}
269
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500270void HostPDRHandler::sendPDRRepositoryChgEvent(std::vector<uint8_t>&& pdrTypes,
271 uint8_t eventDataFormat)
272{
273 assert(eventDataFormat == FORMAT_IS_PDR_HANDLES);
274
275 // Extract from the PDR repo record handles of PDRs we want the host
276 // to pull up.
277 std::vector<uint8_t> eventDataOps{PLDM_RECORDS_ADDED};
278 std::vector<uint8_t> numsOfChangeEntries(1);
279 std::vector<std::vector<ChangeEntry>> changeEntries(
280 numsOfChangeEntries.size());
281 for (auto pdrType : pdrTypes)
282 {
283 const pldm_pdr_record* record{};
284 do
285 {
286 record = pldm_pdr_find_record_by_type(repo, pdrType, record,
287 nullptr, nullptr);
288 if (record && pldm_pdr_record_is_remote(record))
289 {
290 changeEntries[0].push_back(
291 pldm_pdr_get_record_handle(repo, record));
292 }
293 } while (record);
294 }
295 if (changeEntries.empty())
296 {
297 return;
298 }
299 numsOfChangeEntries[0] = changeEntries[0].size();
300
301 // Encode PLDM platform event msg to indicate a PDR repo change.
302 size_t maxSize = PLDM_PDR_REPOSITORY_CHG_EVENT_MIN_LENGTH +
303 PLDM_PDR_REPOSITORY_CHANGE_RECORD_MIN_LENGTH +
304 changeEntries[0].size() * sizeof(uint32_t);
305 std::vector<uint8_t> eventDataVec{};
306 eventDataVec.resize(maxSize);
307 auto eventData =
308 reinterpret_cast<struct pldm_pdr_repository_chg_event_data*>(
309 eventDataVec.data());
310 size_t actualSize{};
311 auto firstEntry = changeEntries[0].data();
312 auto rc = encode_pldm_pdr_repository_chg_event_data(
313 eventDataFormat, 1, eventDataOps.data(), numsOfChangeEntries.data(),
314 &firstEntry, eventData, &actualSize, maxSize);
315 if (rc != PLDM_SUCCESS)
316 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600317 error("Failed to encode_pldm_pdr_repository_chg_event_data, rc = {RC}",
318 "RC", rc);
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500319 return;
320 }
Andrew Jefferya330b2f2023-05-04 14:55:37 +0930321 auto instanceId = instanceIdDb.next(mctp_eid);
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500322 std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) +
323 PLDM_PLATFORM_EVENT_MESSAGE_MIN_REQ_BYTES +
324 actualSize);
325 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
326 rc = encode_platform_event_message_req(
ArchanaKakani6c39c7a2022-12-05 04:36:35 -0600327 instanceId, 1, TERMINUS_ID, PLDM_PDR_REPOSITORY_CHG_EVENT,
328 eventDataVec.data(), actualSize, request,
Christian Geddes3bdb3c22020-05-01 14:55:39 -0500329 actualSize + PLDM_PLATFORM_EVENT_MESSAGE_MIN_REQ_BYTES);
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500330 if (rc != PLDM_SUCCESS)
331 {
Andrew Jefferya330b2f2023-05-04 14:55:37 +0930332 instanceIdDb.free(mctp_eid, instanceId);
Riya Dixit49cfb132023-03-02 04:26:53 -0600333 error("Failed to encode_platform_event_message_req, rc = {RC}", "RC",
334 rc);
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500335 return;
336 }
337
Patrick Williams6da4f912023-05-10 07:50:53 -0500338 auto platformEventMessageResponseHandler =
339 [](mctp_eid_t /*eid*/, const pldm_msg* response, size_t respMsgLen) {
Tom Joseph74f27c72021-05-16 07:58:53 -0700340 if (response == nullptr || !respMsgLen)
341 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600342 error(
343 "Failed to receive response for the PDR repository changed event");
Tom Joseph74f27c72021-05-16 07:58:53 -0700344 return;
345 }
346
347 uint8_t completionCode{};
348 uint8_t status{};
349 auto responsePtr = reinterpret_cast<const struct pldm_msg*>(response);
Pavithra Barithaya54b5a562021-09-27 06:07:10 -0500350 auto rc = decode_platform_event_message_resp(responsePtr, respMsgLen,
351 &completionCode, &status);
Sampa Misrac0c79482021-06-02 08:01:54 -0500352 if (rc || completionCode)
Tom Joseph74f27c72021-05-16 07:58:53 -0700353 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600354 error(
355 "Failed to decode_platform_event_message_resp: {RC}, cc = {CC}",
356 "RC", rc, "CC", static_cast<unsigned>(completionCode));
Tom Joseph74f27c72021-05-16 07:58:53 -0700357 }
358 };
359
Sampa Misrac0c79482021-06-02 08:01:54 -0500360 rc = handler->registerRequest(
Sampa Misra626c5652021-08-11 10:28:48 -0500361 mctp_eid, instanceId, PLDM_PLATFORM, PLDM_PLATFORM_EVENT_MESSAGE,
Tom Joseph74f27c72021-05-16 07:58:53 -0700362 std::move(requestMsg), std::move(platformEventMessageResponseHandler));
Sampa Misrac0c79482021-06-02 08:01:54 -0500363 if (rc)
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500364 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600365 error("Failed to send the PDR repository changed event request");
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500366 }
367}
368
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530369void HostPDRHandler::parseStateSensorPDRs(const PDRList& stateSensorPDRs)
Sampa Misra868c8792020-05-26 03:12:13 -0500370{
371 for (const auto& pdr : stateSensorPDRs)
372 {
373 SensorEntry sensorEntry{};
374 const auto& [terminusHandle, sensorID, sensorInfo] =
375 responder::pdr_utils::parseStateSensorPDR(pdr);
376 sensorEntry.sensorID = sensorID;
377 try
378 {
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530379 sensorEntry.terminusID = std::get<0>(tlPDRInfo.at(terminusHandle));
Sampa Misra868c8792020-05-26 03:12:13 -0500380 }
381 // If there is no mapping for terminusHandle assign the reserved TID
382 // value of 0xFF to indicate that.
383 catch (const std::out_of_range& e)
384 {
385 sensorEntry.terminusID = PLDM_TID_RESERVED;
386 }
387 sensorMap.emplace(sensorEntry, std::move(sensorInfo));
388 }
389}
390
Sampa Misrac0c79482021-06-02 08:01:54 -0500391void HostPDRHandler::processHostPDRs(mctp_eid_t /*eid*/,
392 const pldm_msg* response,
393 size_t respMsgLen)
394{
395 static bool merged = false;
396 static PDRList stateSensorPDRs{};
Sampa Misrac0c79482021-06-02 08:01:54 -0500397 uint32_t nextRecordHandle{};
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600398 uint8_t tlEid = 0;
399 bool tlValid = true;
400 uint32_t rh = 0;
401 uint16_t terminusHandle = 0;
Manojkiran Eda3ca40452021-10-04 22:51:37 +0530402 uint16_t pdrTerminusHandle = 0;
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600403 uint8_t tid = 0;
404
Sampa Misrac0c79482021-06-02 08:01:54 -0500405 uint8_t completionCode{};
406 uint32_t nextDataTransferHandle{};
407 uint8_t transferFlag{};
408 uint16_t respCount{};
409 uint8_t transferCRC{};
410 if (response == nullptr || !respMsgLen)
411 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600412 error("Failed to receive response for the GetPDR command");
Sampa Misrac0c79482021-06-02 08:01:54 -0500413 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 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600425 error("Failed to decode_get_pdr_resp, rc = {RC}", "RC", rc);
Sampa Misrac0c79482021-06-02 08:01:54 -0500426 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 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600437 error("Failed to decode_get_pdr_resp: rc = {RC}, cc = {CC}", "RC",
438 rc, "CC", static_cast<unsigned>(completionCode));
Sampa Misrac0c79482021-06-02 08:01:54 -0500439 return;
440 }
441 else
442 {
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600443 // when nextRecordHandle is 0, we need the recordHandle of the last
444 // PDR and not 0-1.
445 if (!nextRecordHandle)
446 {
447 rh = nextRecordHandle;
448 }
449 else
450 {
451 rh = nextRecordHandle - 1;
452 }
453
Sampa Misrac0c79482021-06-02 08:01:54 -0500454 auto pdrHdr = reinterpret_cast<pldm_pdr_hdr*>(pdr.data());
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600455 if (!rh)
456 {
457 rh = pdrHdr->record_handle;
458 }
459
Sampa Misrac0c79482021-06-02 08:01:54 -0500460 if (pdrHdr->type == PLDM_PDR_ENTITY_ASSOCIATION)
461 {
462 this->mergeEntityAssociations(pdr);
463 merged = true;
464 }
465 else
466 {
467 if (pdrHdr->type == PLDM_TERMINUS_LOCATOR_PDR)
468 {
Manojkiran Eda3ca40452021-10-04 22:51:37 +0530469 pdrTerminusHandle =
470 extractTerminusHandle<pldm_terminus_locator_pdr>(pdr);
Sampa Misrac0c79482021-06-02 08:01:54 -0500471 auto tlpdr =
472 reinterpret_cast<const pldm_terminus_locator_pdr*>(
473 pdr.data());
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600474
475 terminusHandle = tlpdr->terminus_handle;
476 tid = tlpdr->tid;
477 auto terminus_locator_type = tlpdr->terminus_locator_type;
478 if (terminus_locator_type ==
479 PLDM_TERMINUS_LOCATOR_TYPE_MCTP_EID)
480 {
481 auto locatorValue = reinterpret_cast<
482 const pldm_terminus_locator_type_mctp_eid*>(
483 tlpdr->terminus_locator_value);
484 tlEid = static_cast<uint8_t>(locatorValue->eid);
485 }
486 if (tlpdr->validity == 0)
487 {
488 tlValid = false;
489 }
Pavithra Barithaya52aad392022-08-02 04:18:52 -0500490 for (const auto& terminusMap : tlPDRInfo)
491 {
492 if ((terminusHandle == (terminusMap.first)) &&
493 (get<1>(terminusMap.second) == tlEid) &&
494 (get<2>(terminusMap.second) == tlpdr->validity))
495 {
496 // TL PDR already present with same validity don't
497 // add the PDR to the repo just return
498 return;
499 }
500 }
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530501 tlPDRInfo.insert_or_assign(
502 tlpdr->terminus_handle,
503 std::make_tuple(tlpdr->tid, tlEid, tlpdr->validity));
Sampa Misrac0c79482021-06-02 08:01:54 -0500504 }
505 else if (pdrHdr->type == PLDM_STATE_SENSOR_PDR)
506 {
Manojkiran Eda3ca40452021-10-04 22:51:37 +0530507 pdrTerminusHandle =
508 extractTerminusHandle<pldm_state_sensor_pdr>(pdr);
Sampa Misrac0c79482021-06-02 08:01:54 -0500509 stateSensorPDRs.emplace_back(pdr);
510 }
Manojkiran Eda3ca40452021-10-04 22:51:37 +0530511 else if (pdrHdr->type == PLDM_PDR_FRU_RECORD_SET)
512 {
513 pdrTerminusHandle =
514 extractTerminusHandle<pldm_pdr_fru_record_set>(pdr);
515 }
516 else if (pdrHdr->type == PLDM_STATE_EFFECTER_PDR)
517 {
518 pdrTerminusHandle =
519 extractTerminusHandle<pldm_state_effecter_pdr>(pdr);
520 }
521 else if (pdrHdr->type == PLDM_NUMERIC_EFFECTER_PDR)
522 {
523 pdrTerminusHandle =
524 extractTerminusHandle<pldm_numeric_effecter_value_pdr>(
525 pdr);
526 }
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600527 // if the TLPDR is invalid update the repo accordingly
528 if (!tlValid)
529 {
530 pldm_pdr_update_TL_pdr(repo, terminusHandle, tid, tlEid,
531 tlValid);
532 }
533 else
534 {
Andrew Jeffery64f37fe2023-07-03 15:41:13 +0930535 rc = pldm_pdr_add_check(repo, pdr.data(), respCount, true,
536 pdrTerminusHandle, &rh);
537 if (rc)
538 {
539 // pldm_pdr_add() assert()ed on failure to add a PDR.
540 throw std::runtime_error("Failed to add PDR");
541 }
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600542 }
Sampa Misrac0c79482021-06-02 08:01:54 -0500543 }
544 }
545 }
546 if (!nextRecordHandle)
547 {
548 /*received last record*/
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530549 this->parseStateSensorPDRs(stateSensorPDRs);
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600550 if (isHostUp())
551 {
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530552 this->setHostSensorState(stateSensorPDRs);
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600553 }
Sampa Misrac0c79482021-06-02 08:01:54 -0500554 stateSensorPDRs.clear();
Sampa Misrac0c79482021-06-02 08:01:54 -0500555 if (merged)
556 {
557 merged = false;
558 deferredPDRRepoChgEvent =
559 std::make_unique<sdeventplus::source::Defer>(
560 event,
561 std::bind(
562 std::mem_fn((&HostPDRHandler::_processPDRRepoChgEvent)),
563 this, std::placeholders::_1));
564 }
565 }
566 else
567 {
Pavithra Barithayaae5c97e2022-08-29 02:57:59 -0500568 if (modifiedPDRRecordHandles.empty() && isHostPdrModified)
569 {
570 isHostPdrModified = false;
571 }
572 else
573 {
574 deferredFetchPDREvent =
575 std::make_unique<sdeventplus::source::Defer>(
576 event,
577 std::bind(
578 std::mem_fn((&HostPDRHandler::_processFetchPDREvent)),
579 this, nextRecordHandle, std::placeholders::_1));
580 }
Sampa Misrac0c79482021-06-02 08:01:54 -0500581 }
582}
583
584void HostPDRHandler::_processPDRRepoChgEvent(
585 sdeventplus::source::EventBase& /*source */)
586{
587 deferredPDRRepoChgEvent.reset();
588 this->sendPDRRepositoryChgEvent(
589 std::move(std::vector<uint8_t>(1, PLDM_PDR_ENTITY_ASSOCIATION)),
590 FORMAT_IS_PDR_HANDLES);
591}
592
593void HostPDRHandler::_processFetchPDREvent(
594 uint32_t nextRecordHandle, sdeventplus::source::EventBase& /*source */)
595{
596 deferredFetchPDREvent.reset();
597 if (!this->pdrRecordHandles.empty())
598 {
599 nextRecordHandle = this->pdrRecordHandles.front();
600 this->pdrRecordHandles.pop_front();
601 }
Pavithra Barithayaae5c97e2022-08-29 02:57:59 -0500602 if (isHostPdrModified && (!this->modifiedPDRRecordHandles.empty()))
603 {
604 nextRecordHandle = this->modifiedPDRRecordHandles.front();
605 this->modifiedPDRRecordHandles.pop_front();
606 }
Sampa Misrac0c79482021-06-02 08:01:54 -0500607 this->getHostPDR(nextRecordHandle);
608}
609
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500610void HostPDRHandler::setHostFirmwareCondition()
sampmisr6decfc12021-03-02 11:07:36 +0530611{
sampmisr6decfc12021-03-02 11:07:36 +0530612 responseReceived = false;
Andrew Jefferya330b2f2023-05-04 14:55:37 +0930613 auto instanceId = instanceIdDb.next(mctp_eid);
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500614 std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) +
615 PLDM_GET_VERSION_REQ_BYTES);
616 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
617 auto rc = encode_get_version_req(instanceId, 0, PLDM_GET_FIRSTPART,
618 PLDM_BASE, request);
619 if (rc != PLDM_SUCCESS)
sampmisr6decfc12021-03-02 11:07:36 +0530620 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600621 error("GetPLDMVersion encode failure. PLDM error code = {RC}", "RC",
622 lg2::hex, rc);
Andrew Jefferya330b2f2023-05-04 14:55:37 +0930623 instanceIdDb.free(mctp_eid, instanceId);
sampmisr6decfc12021-03-02 11:07:36 +0530624 return;
625 }
626
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500627 auto getPLDMVersionHandler = [this](mctp_eid_t /*eid*/,
628 const pldm_msg* response,
629 size_t respMsgLen) {
630 if (response == nullptr || !respMsgLen)
sampmisr6decfc12021-03-02 11:07:36 +0530631 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600632 error(
633 "Failed to receive response for getPLDMVersion command, Host seems to be off");
sampmisr6decfc12021-03-02 11:07:36 +0530634 return;
635 }
Riya Dixit49cfb132023-03-02 04:26:53 -0600636 info("Getting the response. PLDM RC = {RC}", "RC", lg2::hex,
637 static_cast<uint16_t>(response->payload[0]));
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500638 this->responseReceived = true;
639 getHostPDR();
sampmisr6decfc12021-03-02 11:07:36 +0530640 };
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500641 rc = handler->registerRequest(mctp_eid, instanceId, PLDM_BASE,
642 PLDM_GET_PLDM_VERSION, std::move(requestMsg),
643 std::move(getPLDMVersionHandler));
644 if (rc)
sampmisr6decfc12021-03-02 11:07:36 +0530645 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600646 error("Failed to discover Host state. Assuming Host as off");
sampmisr6decfc12021-03-02 11:07:36 +0530647 }
648}
649
650bool HostPDRHandler::isHostUp()
651{
652 return responseReceived;
653}
654
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530655void HostPDRHandler::setHostSensorState(const PDRList& stateSensorPDRs)
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600656{
657 for (const auto& stateSensorPDR : stateSensorPDRs)
658 {
659 auto pdr = reinterpret_cast<const pldm_state_sensor_pdr*>(
660 stateSensorPDR.data());
661
662 if (!pdr)
663 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600664 error("Failed to get State sensor PDR");
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600665 pldm::utils::reportError(
666 "xyz.openbmc_project.bmc.pldm.InternalFailure");
667 return;
668 }
669
670 uint16_t sensorId = pdr->sensor_id;
671
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530672 for (const auto& [terminusHandle, terminusInfo] : tlPDRInfo)
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600673 {
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530674 if (terminusHandle == pdr->terminus_handle)
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600675 {
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530676 if (std::get<2>(terminusInfo) == PLDM_TL_PDR_VALID)
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600677 {
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530678 mctp_eid = std::get<1>(terminusInfo);
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600679 }
680
681 bitfield8_t sensorRearm;
682 sensorRearm.byte = 0;
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530683 uint8_t tid = std::get<0>(terminusInfo);
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600684
Andrew Jefferya330b2f2023-05-04 14:55:37 +0930685 auto instanceId = instanceIdDb.next(mctp_eid);
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600686 std::vector<uint8_t> requestMsg(
687 sizeof(pldm_msg_hdr) +
688 PLDM_GET_STATE_SENSOR_READINGS_REQ_BYTES);
689 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
690 auto rc = encode_get_state_sensor_readings_req(
691 instanceId, sensorId, sensorRearm, 0, request);
692
693 if (rc != PLDM_SUCCESS)
694 {
Andrew Jefferya330b2f2023-05-04 14:55:37 +0930695 instanceIdDb.free(mctp_eid, instanceId);
Riya Dixit49cfb132023-03-02 04:26:53 -0600696 error(
697 "Failed to encode_get_state_sensor_readings_req, rc = {RC}",
698 "RC", rc);
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600699 pldm::utils::reportError(
700 "xyz.openbmc_project.bmc.pldm.InternalFailure");
701 return;
702 }
703
Patrick Williams6da4f912023-05-10 07:50:53 -0500704 auto getStateSensorReadingRespHandler =
705 [=, this](mctp_eid_t /*eid*/, const pldm_msg* response,
706 size_t respMsgLen) {
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600707 if (response == nullptr || !respMsgLen)
708 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600709 error(
710 "Failed to receive response for getStateSensorReading command");
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600711 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 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600723 error(
724 "Failed to decode_get_state_sensor_readings_resp, rc = {RC} cc = {CC}",
725 "RC", rc, "CC",
726 static_cast<unsigned>(completionCode));
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600727 pldm::utils::reportError(
728 "xyz.openbmc_project.bmc.pldm.InternalFailure");
729 }
730
731 uint8_t eventState;
732 uint8_t previousEventState;
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600733
RIYA DIXITbb5fda42022-09-27 06:48:08 -0500734 for (uint8_t sensorOffset = 0;
735 sensorOffset < comp_sensor_count; sensorOffset++)
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600736 {
RIYA DIXITbb5fda42022-09-27 06:48:08 -0500737 eventState = stateField[sensorOffset].present_state;
738 previousEventState =
739 stateField[sensorOffset].previous_state;
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600740
741 emitStateSensorEventSignal(tid, sensorId, sensorOffset,
742 eventState,
743 previousEventState);
744
745 SensorEntry sensorEntry{tid, sensorId};
746
747 pldm::pdr::EntityInfo entityInfo{};
748 pldm::pdr::CompositeSensorStates
749 compositeSensorStates{};
750
751 try
752 {
753 std::tie(entityInfo, compositeSensorStates) =
754 lookupSensorInfo(sensorEntry);
755 }
756 catch (const std::out_of_range& e)
757 {
758 try
759 {
760 sensorEntry.terminusID = PLDM_TID_RESERVED;
761 std::tie(entityInfo, compositeSensorStates) =
762 lookupSensorInfo(sensorEntry);
763 }
764 catch (const std::out_of_range& e)
765 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600766 error("No mapping for the events");
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600767 }
768 }
769
770 if (sensorOffset > compositeSensorStates.size())
771 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600772 error("Error Invalid data, Invalid sensor offset");
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600773 return;
774 }
775
776 const auto& possibleStates =
777 compositeSensorStates[sensorOffset];
778 if (possibleStates.find(eventState) ==
779 possibleStates.end())
780 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600781 error("Error invalid_data, Invalid event state");
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600782 return;
783 }
Patrick Williams6da4f912023-05-10 07:50:53 -0500784 const auto& [containerId, entityType,
785 entityInstance] = entityInfo;
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600786 pldm::responder::events::StateSensorEntry
787 stateSensorEntry{containerId, entityType,
788 entityInstance, sensorOffset};
789 handleStateSensorEvent(stateSensorEntry, eventState);
790 }
791 };
792
793 rc = handler->registerRequest(
794 mctp_eid, instanceId, PLDM_PLATFORM,
795 PLDM_GET_STATE_SENSOR_READINGS, std::move(requestMsg),
796 std::move(getStateSensorReadingRespHandler));
797
798 if (rc != PLDM_SUCCESS)
799 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600800 error(
801 "Failed to send request to get State sensor reading on Host");
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600802 }
803 }
804 }
805 }
806}
Pavithra Barithaya51efaf82020-04-02 02:42:27 -0500807} // namespace pldm