blob: 3ceae13a2c2ec0376e14c862173e3bba6d22cdc1 [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{
George Liuacf2c8c2021-05-10 14:08:52 +080058 mergedHostParents = false;
Deepak Kodihalli87514cc2020-04-16 09:08:38 -050059 fs::path hostFruJson(fs::path(HOST_JSONS_DIR) / fruJson);
60 if (fs::exists(hostFruJson))
61 {
Pavithra Barithayae8beb892020-04-14 23:24:25 -050062 // Note parent entities for entities sent down by the host firmware.
63 // This will enable a merge of entity associations.
Deepak Kodihalli87514cc2020-04-16 09:08:38 -050064 try
65 {
66 std::ifstream jsonFile(hostFruJson);
67 auto data = Json::parse(jsonFile, nullptr, false);
68 if (data.is_discarded())
69 {
Riya Dixit49cfb132023-03-02 04:26:53 -060070 error("Parsing Host FRU json file failed");
Deepak Kodihalli87514cc2020-04-16 09:08:38 -050071 }
72 else
73 {
74 auto entities = data.value("entities", emptyJsonList);
75 for (auto& entity : entities)
76 {
77 EntityType entityType = entity.value("entity_type", 0);
78 auto parent = entity.value("parent", emptyJson);
79 pldm_entity p{};
80 p.entity_type = parent.value("entity_type", 0);
81 p.entity_instance_num = parent.value("entity_instance", 0);
82 parents.emplace(entityType, std::move(p));
83 }
84 }
85 }
86 catch (const std::exception& e)
87 {
Riya Dixit49cfb132023-03-02 04:26:53 -060088 error("Parsing Host FRU json file failed, exception = {ERR_EXCEP}",
89 "ERR_EXCEP", e.what());
Deepak Kodihalli87514cc2020-04-16 09:08:38 -050090 }
91 }
Deepak Kodihalli6b1d1ca2020-04-27 07:24:51 -050092
Patrick Williams84b790c2022-07-22 19:26:56 -050093 hostOffMatch = std::make_unique<sdbusplus::bus::match_t>(
Deepak Kodihalli6b1d1ca2020-04-27 07:24:51 -050094 pldm::utils::DBusHandler::getBus(),
95 propertiesChanged("/xyz/openbmc_project/state/host0",
96 "xyz.openbmc_project.State.Host"),
Patrick Williams84b790c2022-07-22 19:26:56 -050097 [this, repo, entityTree, bmcEntityTree](sdbusplus::message_t& msg) {
Patrick Williams6da4f912023-05-10 07:50:53 -050098 DbusChangedProps props{};
99 std::string intf;
100 msg.read(intf, props);
101 const auto itr = props.find("CurrentHostState");
102 if (itr != props.end())
103 {
104 PropertyValue value = itr->second;
105 auto propVal = std::get<std::string>(value);
106 if (propVal == "xyz.openbmc_project.State.Host.HostState.Off")
Deepak Kodihalli6b1d1ca2020-04-27 07:24:51 -0500107 {
Patrick Williams6da4f912023-05-10 07:50:53 -0500108 // Delete all the remote terminus information
109 std::erase_if(tlPDRInfo, [](const auto& item) {
110 auto const& [key, value] = item;
111 return key != TERMINUS_HANDLE;
112 });
113 pldm_pdr_remove_remote_pdrs(repo);
114 pldm_entity_association_tree_destroy_root(entityTree);
115 pldm_entity_association_tree_copy_root(bmcEntityTree,
116 entityTree);
117 this->sensorMap.clear();
118 this->responseReceived = false;
George Liuacf2c8c2021-05-10 14:08:52 +0800119 this->mergedHostParents = 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 -0500208
209void HostPDRHandler::mergeEntityAssociations(const std::vector<uint8_t>& pdr)
210{
211 size_t numEntities{};
212 pldm_entity* entities = nullptr;
213 bool merged = false;
214 auto entityPdr = reinterpret_cast<pldm_pdr_entity_association*>(
215 const_cast<uint8_t*>(pdr.data()) + sizeof(pldm_pdr_hdr));
216
217 pldm_entity_association_pdr_extract(pdr.data(), pdr.size(), &numEntities,
218 &entities);
George Liuacf2c8c2021-05-10 14:08:52 +0800219 if (numEntities > 0)
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500220 {
George Liuacf2c8c2021-05-10 14:08:52 +0800221 pldm_entity_node* pNode = nullptr;
222 if (!mergedHostParents)
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500223 {
George Liuacf2c8c2021-05-10 14:08:52 +0800224 pNode = pldm_entity_association_tree_find_with_locality(
225 entityTree, &entities[0], false);
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500226 }
George Liuacf2c8c2021-05-10 14:08:52 +0800227 else
228 {
229 pNode = pldm_entity_association_tree_find_with_locality(
230 entityTree, &entities[0], true);
231 }
232 if (!pNode)
233 {
234 return;
235 }
236
George Liudf9a6d32020-12-22 16:27:16 +0800237 Entities entityAssoc;
238 entityAssoc.push_back(pNode);
George Liuacf2c8c2021-05-10 14:08:52 +0800239 for (size_t i = 1; i < numEntities; ++i)
240 {
George Liudf9a6d32020-12-22 16:27:16 +0800241 auto node = pldm_entity_association_tree_add_entity(
George Liuacf2c8c2021-05-10 14:08:52 +0800242 entityTree, &entities[i], entities[i].entity_instance_num,
243 pNode, entityPdr->association_type, true, true, 0xFFFF);
244 merged = true;
George Liudf9a6d32020-12-22 16:27:16 +0800245 entityAssoc.push_back(node);
George Liuacf2c8c2021-05-10 14:08:52 +0800246 }
247
248 mergedHostParents = true;
George Liudf9a6d32020-12-22 16:27:16 +0800249 if (merged)
250 {
251 entityAssociations.push_back(entityAssoc);
252 }
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500253 }
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500254
255 if (merged)
256 {
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500257 // Update our PDR repo with the merged entity association PDRs
Sampa Misra719ed392021-06-04 05:15:13 -0500258 pldm_entity_node* node = nullptr;
259 pldm_find_entity_ref_in_tree(entityTree, entities[0], &node);
260 if (node == nullptr)
261 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600262 error("could not find referrence of the entity in the tree");
Sampa Misra719ed392021-06-04 05:15:13 -0500263 }
264 else
265 {
Andrew Jeffery1fd3c512023-07-03 13:02:03 +0930266 int rc = pldm_entity_association_pdr_add_from_node_check(
Manojkiran Eda3ca40452021-10-04 22:51:37 +0530267 node, repo, &entities, numEntities, true, TERMINUS_HANDLE);
Andrew Jeffery1fd3c512023-07-03 13:02:03 +0930268 if (rc)
269 {
270 error(
271 "Failed to add entity association PDR from node: {LIBPLDM_ERROR}",
272 "LIBPLDM_ERROR", rc);
273 }
Sampa Misra719ed392021-06-04 05:15:13 -0500274 }
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500275 }
Sampa Misra719ed392021-06-04 05:15:13 -0500276 free(entities);
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500277}
278
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500279void HostPDRHandler::sendPDRRepositoryChgEvent(std::vector<uint8_t>&& pdrTypes,
280 uint8_t eventDataFormat)
281{
282 assert(eventDataFormat == FORMAT_IS_PDR_HANDLES);
283
284 // Extract from the PDR repo record handles of PDRs we want the host
285 // to pull up.
286 std::vector<uint8_t> eventDataOps{PLDM_RECORDS_ADDED};
287 std::vector<uint8_t> numsOfChangeEntries(1);
288 std::vector<std::vector<ChangeEntry>> changeEntries(
289 numsOfChangeEntries.size());
290 for (auto pdrType : pdrTypes)
291 {
292 const pldm_pdr_record* record{};
293 do
294 {
295 record = pldm_pdr_find_record_by_type(repo, pdrType, record,
296 nullptr, nullptr);
297 if (record && pldm_pdr_record_is_remote(record))
298 {
299 changeEntries[0].push_back(
300 pldm_pdr_get_record_handle(repo, record));
301 }
302 } while (record);
303 }
304 if (changeEntries.empty())
305 {
306 return;
307 }
308 numsOfChangeEntries[0] = changeEntries[0].size();
309
310 // Encode PLDM platform event msg to indicate a PDR repo change.
311 size_t maxSize = PLDM_PDR_REPOSITORY_CHG_EVENT_MIN_LENGTH +
312 PLDM_PDR_REPOSITORY_CHANGE_RECORD_MIN_LENGTH +
313 changeEntries[0].size() * sizeof(uint32_t);
314 std::vector<uint8_t> eventDataVec{};
315 eventDataVec.resize(maxSize);
316 auto eventData =
317 reinterpret_cast<struct pldm_pdr_repository_chg_event_data*>(
318 eventDataVec.data());
319 size_t actualSize{};
320 auto firstEntry = changeEntries[0].data();
321 auto rc = encode_pldm_pdr_repository_chg_event_data(
322 eventDataFormat, 1, eventDataOps.data(), numsOfChangeEntries.data(),
323 &firstEntry, eventData, &actualSize, maxSize);
324 if (rc != PLDM_SUCCESS)
325 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600326 error("Failed to encode_pldm_pdr_repository_chg_event_data, rc = {RC}",
327 "RC", rc);
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500328 return;
329 }
Andrew Jefferya330b2f2023-05-04 14:55:37 +0930330 auto instanceId = instanceIdDb.next(mctp_eid);
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500331 std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) +
332 PLDM_PLATFORM_EVENT_MESSAGE_MIN_REQ_BYTES +
333 actualSize);
334 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
335 rc = encode_platform_event_message_req(
ArchanaKakani6c39c7a2022-12-05 04:36:35 -0600336 instanceId, 1, TERMINUS_ID, PLDM_PDR_REPOSITORY_CHG_EVENT,
337 eventDataVec.data(), actualSize, request,
Christian Geddes3bdb3c22020-05-01 14:55:39 -0500338 actualSize + PLDM_PLATFORM_EVENT_MESSAGE_MIN_REQ_BYTES);
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500339 if (rc != PLDM_SUCCESS)
340 {
Andrew Jefferya330b2f2023-05-04 14:55:37 +0930341 instanceIdDb.free(mctp_eid, instanceId);
Riya Dixit49cfb132023-03-02 04:26:53 -0600342 error("Failed to encode_platform_event_message_req, rc = {RC}", "RC",
343 rc);
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500344 return;
345 }
346
Patrick Williams6da4f912023-05-10 07:50:53 -0500347 auto platformEventMessageResponseHandler =
348 [](mctp_eid_t /*eid*/, const pldm_msg* response, size_t respMsgLen) {
Tom Joseph74f27c72021-05-16 07:58:53 -0700349 if (response == nullptr || !respMsgLen)
350 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600351 error(
352 "Failed to receive response for the PDR repository changed event");
Tom Joseph74f27c72021-05-16 07:58:53 -0700353 return;
354 }
355
356 uint8_t completionCode{};
357 uint8_t status{};
358 auto responsePtr = reinterpret_cast<const struct pldm_msg*>(response);
Pavithra Barithaya54b5a562021-09-27 06:07:10 -0500359 auto rc = decode_platform_event_message_resp(responsePtr, respMsgLen,
360 &completionCode, &status);
Sampa Misrac0c79482021-06-02 08:01:54 -0500361 if (rc || completionCode)
Tom Joseph74f27c72021-05-16 07:58:53 -0700362 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600363 error(
364 "Failed to decode_platform_event_message_resp: {RC}, cc = {CC}",
365 "RC", rc, "CC", static_cast<unsigned>(completionCode));
Tom Joseph74f27c72021-05-16 07:58:53 -0700366 }
367 };
368
Sampa Misrac0c79482021-06-02 08:01:54 -0500369 rc = handler->registerRequest(
Sampa Misra626c5652021-08-11 10:28:48 -0500370 mctp_eid, instanceId, PLDM_PLATFORM, PLDM_PLATFORM_EVENT_MESSAGE,
Tom Joseph74f27c72021-05-16 07:58:53 -0700371 std::move(requestMsg), std::move(platformEventMessageResponseHandler));
Sampa Misrac0c79482021-06-02 08:01:54 -0500372 if (rc)
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500373 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600374 error("Failed to send the PDR repository changed event request");
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500375 }
376}
377
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530378void HostPDRHandler::parseStateSensorPDRs(const PDRList& stateSensorPDRs)
Sampa Misra868c8792020-05-26 03:12:13 -0500379{
380 for (const auto& pdr : stateSensorPDRs)
381 {
382 SensorEntry sensorEntry{};
383 const auto& [terminusHandle, sensorID, sensorInfo] =
384 responder::pdr_utils::parseStateSensorPDR(pdr);
385 sensorEntry.sensorID = sensorID;
386 try
387 {
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530388 sensorEntry.terminusID = std::get<0>(tlPDRInfo.at(terminusHandle));
Sampa Misra868c8792020-05-26 03:12:13 -0500389 }
390 // If there is no mapping for terminusHandle assign the reserved TID
391 // value of 0xFF to indicate that.
392 catch (const std::out_of_range& e)
393 {
394 sensorEntry.terminusID = PLDM_TID_RESERVED;
395 }
396 sensorMap.emplace(sensorEntry, std::move(sensorInfo));
397 }
398}
399
Sampa Misrac0c79482021-06-02 08:01:54 -0500400void HostPDRHandler::processHostPDRs(mctp_eid_t /*eid*/,
401 const pldm_msg* response,
402 size_t respMsgLen)
403{
404 static bool merged = false;
405 static PDRList stateSensorPDRs{};
Sampa Misrac0c79482021-06-02 08:01:54 -0500406 uint32_t nextRecordHandle{};
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600407 uint8_t tlEid = 0;
408 bool tlValid = true;
409 uint32_t rh = 0;
410 uint16_t terminusHandle = 0;
Manojkiran Eda3ca40452021-10-04 22:51:37 +0530411 uint16_t pdrTerminusHandle = 0;
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600412 uint8_t tid = 0;
413
Sampa Misrac0c79482021-06-02 08:01:54 -0500414 uint8_t completionCode{};
415 uint32_t nextDataTransferHandle{};
416 uint8_t transferFlag{};
417 uint16_t respCount{};
418 uint8_t transferCRC{};
419 if (response == nullptr || !respMsgLen)
420 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600421 error("Failed to receive response for the GetPDR command");
Sampa Misrac0c79482021-06-02 08:01:54 -0500422 return;
423 }
424
425 auto rc = decode_get_pdr_resp(
426 response, respMsgLen /*- sizeof(pldm_msg_hdr)*/, &completionCode,
427 &nextRecordHandle, &nextDataTransferHandle, &transferFlag, &respCount,
428 nullptr, 0, &transferCRC);
429 std::vector<uint8_t> responsePDRMsg;
430 responsePDRMsg.resize(respMsgLen + sizeof(pldm_msg_hdr));
431 memcpy(responsePDRMsg.data(), response, respMsgLen + sizeof(pldm_msg_hdr));
Sampa Misrac0c79482021-06-02 08:01:54 -0500432 if (rc != PLDM_SUCCESS)
433 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600434 error("Failed to decode_get_pdr_resp, rc = {RC}", "RC", rc);
Sampa Misrac0c79482021-06-02 08:01:54 -0500435 return;
436 }
437 else
438 {
439 std::vector<uint8_t> pdr(respCount, 0);
440 rc = decode_get_pdr_resp(response, respMsgLen, &completionCode,
441 &nextRecordHandle, &nextDataTransferHandle,
442 &transferFlag, &respCount, pdr.data(),
443 respCount, &transferCRC);
444 if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS)
445 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600446 error("Failed to decode_get_pdr_resp: rc = {RC}, cc = {CC}", "RC",
447 rc, "CC", static_cast<unsigned>(completionCode));
Sampa Misrac0c79482021-06-02 08:01:54 -0500448 return;
449 }
450 else
451 {
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600452 // when nextRecordHandle is 0, we need the recordHandle of the last
453 // PDR and not 0-1.
454 if (!nextRecordHandle)
455 {
456 rh = nextRecordHandle;
457 }
458 else
459 {
460 rh = nextRecordHandle - 1;
461 }
462
Sampa Misrac0c79482021-06-02 08:01:54 -0500463 auto pdrHdr = reinterpret_cast<pldm_pdr_hdr*>(pdr.data());
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600464 if (!rh)
465 {
466 rh = pdrHdr->record_handle;
467 }
468
Sampa Misrac0c79482021-06-02 08:01:54 -0500469 if (pdrHdr->type == PLDM_PDR_ENTITY_ASSOCIATION)
470 {
471 this->mergeEntityAssociations(pdr);
472 merged = true;
473 }
474 else
475 {
476 if (pdrHdr->type == PLDM_TERMINUS_LOCATOR_PDR)
477 {
Manojkiran Eda3ca40452021-10-04 22:51:37 +0530478 pdrTerminusHandle =
479 extractTerminusHandle<pldm_terminus_locator_pdr>(pdr);
Sampa Misrac0c79482021-06-02 08:01:54 -0500480 auto tlpdr =
481 reinterpret_cast<const pldm_terminus_locator_pdr*>(
482 pdr.data());
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600483
484 terminusHandle = tlpdr->terminus_handle;
485 tid = tlpdr->tid;
486 auto terminus_locator_type = tlpdr->terminus_locator_type;
487 if (terminus_locator_type ==
488 PLDM_TERMINUS_LOCATOR_TYPE_MCTP_EID)
489 {
490 auto locatorValue = reinterpret_cast<
491 const pldm_terminus_locator_type_mctp_eid*>(
492 tlpdr->terminus_locator_value);
493 tlEid = static_cast<uint8_t>(locatorValue->eid);
494 }
495 if (tlpdr->validity == 0)
496 {
497 tlValid = false;
498 }
Pavithra Barithaya52aad392022-08-02 04:18:52 -0500499 for (const auto& terminusMap : tlPDRInfo)
500 {
501 if ((terminusHandle == (terminusMap.first)) &&
502 (get<1>(terminusMap.second) == tlEid) &&
503 (get<2>(terminusMap.second) == tlpdr->validity))
504 {
505 // TL PDR already present with same validity don't
506 // add the PDR to the repo just return
507 return;
508 }
509 }
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530510 tlPDRInfo.insert_or_assign(
511 tlpdr->terminus_handle,
512 std::make_tuple(tlpdr->tid, tlEid, tlpdr->validity));
Sampa Misrac0c79482021-06-02 08:01:54 -0500513 }
514 else if (pdrHdr->type == PLDM_STATE_SENSOR_PDR)
515 {
Manojkiran Eda3ca40452021-10-04 22:51:37 +0530516 pdrTerminusHandle =
517 extractTerminusHandle<pldm_state_sensor_pdr>(pdr);
Sampa Misrac0c79482021-06-02 08:01:54 -0500518 stateSensorPDRs.emplace_back(pdr);
519 }
Manojkiran Eda3ca40452021-10-04 22:51:37 +0530520 else if (pdrHdr->type == PLDM_PDR_FRU_RECORD_SET)
521 {
522 pdrTerminusHandle =
523 extractTerminusHandle<pldm_pdr_fru_record_set>(pdr);
524 }
525 else if (pdrHdr->type == PLDM_STATE_EFFECTER_PDR)
526 {
527 pdrTerminusHandle =
528 extractTerminusHandle<pldm_state_effecter_pdr>(pdr);
529 }
530 else if (pdrHdr->type == PLDM_NUMERIC_EFFECTER_PDR)
531 {
532 pdrTerminusHandle =
533 extractTerminusHandle<pldm_numeric_effecter_value_pdr>(
534 pdr);
535 }
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600536 // if the TLPDR is invalid update the repo accordingly
537 if (!tlValid)
538 {
539 pldm_pdr_update_TL_pdr(repo, terminusHandle, tid, tlEid,
540 tlValid);
541 }
542 else
543 {
Andrew Jeffery64f37fe2023-07-03 15:41:13 +0930544 rc = pldm_pdr_add_check(repo, pdr.data(), respCount, true,
545 pdrTerminusHandle, &rh);
546 if (rc)
547 {
548 // pldm_pdr_add() assert()ed on failure to add a PDR.
549 throw std::runtime_error("Failed to add PDR");
550 }
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600551 }
Sampa Misrac0c79482021-06-02 08:01:54 -0500552 }
553 }
554 }
555 if (!nextRecordHandle)
556 {
George Liudf9a6d32020-12-22 16:27:16 +0800557 updateEntityAssociation(entityAssociations, entityTree, objPathMap);
558
Sampa Misrac0c79482021-06-02 08:01:54 -0500559 /*received last record*/
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530560 this->parseStateSensorPDRs(stateSensorPDRs);
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600561 if (isHostUp())
562 {
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530563 this->setHostSensorState(stateSensorPDRs);
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600564 }
Sampa Misrac0c79482021-06-02 08:01:54 -0500565 stateSensorPDRs.clear();
George Liudf9a6d32020-12-22 16:27:16 +0800566 entityAssociations.clear();
567
Sampa Misrac0c79482021-06-02 08:01:54 -0500568 if (merged)
569 {
570 merged = false;
571 deferredPDRRepoChgEvent =
572 std::make_unique<sdeventplus::source::Defer>(
573 event,
574 std::bind(
575 std::mem_fn((&HostPDRHandler::_processPDRRepoChgEvent)),
576 this, std::placeholders::_1));
577 }
578 }
579 else
580 {
Pavithra Barithayaae5c97e2022-08-29 02:57:59 -0500581 if (modifiedPDRRecordHandles.empty() && isHostPdrModified)
582 {
583 isHostPdrModified = false;
584 }
585 else
586 {
587 deferredFetchPDREvent =
588 std::make_unique<sdeventplus::source::Defer>(
589 event,
590 std::bind(
591 std::mem_fn((&HostPDRHandler::_processFetchPDREvent)),
592 this, nextRecordHandle, std::placeholders::_1));
593 }
Sampa Misrac0c79482021-06-02 08:01:54 -0500594 }
595}
596
597void HostPDRHandler::_processPDRRepoChgEvent(
598 sdeventplus::source::EventBase& /*source */)
599{
600 deferredPDRRepoChgEvent.reset();
601 this->sendPDRRepositoryChgEvent(
602 std::move(std::vector<uint8_t>(1, PLDM_PDR_ENTITY_ASSOCIATION)),
603 FORMAT_IS_PDR_HANDLES);
604}
605
606void HostPDRHandler::_processFetchPDREvent(
607 uint32_t nextRecordHandle, sdeventplus::source::EventBase& /*source */)
608{
609 deferredFetchPDREvent.reset();
610 if (!this->pdrRecordHandles.empty())
611 {
612 nextRecordHandle = this->pdrRecordHandles.front();
613 this->pdrRecordHandles.pop_front();
614 }
Pavithra Barithayaae5c97e2022-08-29 02:57:59 -0500615 if (isHostPdrModified && (!this->modifiedPDRRecordHandles.empty()))
616 {
617 nextRecordHandle = this->modifiedPDRRecordHandles.front();
618 this->modifiedPDRRecordHandles.pop_front();
619 }
Sampa Misrac0c79482021-06-02 08:01:54 -0500620 this->getHostPDR(nextRecordHandle);
621}
622
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500623void HostPDRHandler::setHostFirmwareCondition()
sampmisr6decfc12021-03-02 11:07:36 +0530624{
sampmisr6decfc12021-03-02 11:07:36 +0530625 responseReceived = false;
Andrew Jefferya330b2f2023-05-04 14:55:37 +0930626 auto instanceId = instanceIdDb.next(mctp_eid);
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500627 std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) +
628 PLDM_GET_VERSION_REQ_BYTES);
629 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
630 auto rc = encode_get_version_req(instanceId, 0, PLDM_GET_FIRSTPART,
631 PLDM_BASE, request);
632 if (rc != PLDM_SUCCESS)
sampmisr6decfc12021-03-02 11:07:36 +0530633 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600634 error("GetPLDMVersion encode failure. PLDM error code = {RC}", "RC",
635 lg2::hex, rc);
Andrew Jefferya330b2f2023-05-04 14:55:37 +0930636 instanceIdDb.free(mctp_eid, instanceId);
sampmisr6decfc12021-03-02 11:07:36 +0530637 return;
638 }
639
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500640 auto getPLDMVersionHandler = [this](mctp_eid_t /*eid*/,
641 const pldm_msg* response,
642 size_t respMsgLen) {
643 if (response == nullptr || !respMsgLen)
sampmisr6decfc12021-03-02 11:07:36 +0530644 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600645 error(
646 "Failed to receive response for getPLDMVersion command, Host seems to be off");
sampmisr6decfc12021-03-02 11:07:36 +0530647 return;
648 }
Riya Dixit49cfb132023-03-02 04:26:53 -0600649 info("Getting the response. PLDM RC = {RC}", "RC", lg2::hex,
650 static_cast<uint16_t>(response->payload[0]));
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500651 this->responseReceived = true;
652 getHostPDR();
sampmisr6decfc12021-03-02 11:07:36 +0530653 };
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500654 rc = handler->registerRequest(mctp_eid, instanceId, PLDM_BASE,
655 PLDM_GET_PLDM_VERSION, std::move(requestMsg),
656 std::move(getPLDMVersionHandler));
657 if (rc)
sampmisr6decfc12021-03-02 11:07:36 +0530658 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600659 error("Failed to discover Host state. Assuming Host as off");
sampmisr6decfc12021-03-02 11:07:36 +0530660 }
661}
662
663bool HostPDRHandler::isHostUp()
664{
665 return responseReceived;
666}
667
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530668void HostPDRHandler::setHostSensorState(const PDRList& stateSensorPDRs)
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600669{
670 for (const auto& stateSensorPDR : stateSensorPDRs)
671 {
672 auto pdr = reinterpret_cast<const pldm_state_sensor_pdr*>(
673 stateSensorPDR.data());
674
675 if (!pdr)
676 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600677 error("Failed to get State sensor PDR");
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600678 pldm::utils::reportError(
679 "xyz.openbmc_project.bmc.pldm.InternalFailure");
680 return;
681 }
682
683 uint16_t sensorId = pdr->sensor_id;
684
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530685 for (const auto& [terminusHandle, terminusInfo] : tlPDRInfo)
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600686 {
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530687 if (terminusHandle == pdr->terminus_handle)
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600688 {
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530689 if (std::get<2>(terminusInfo) == PLDM_TL_PDR_VALID)
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600690 {
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530691 mctp_eid = std::get<1>(terminusInfo);
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600692 }
693
694 bitfield8_t sensorRearm;
695 sensorRearm.byte = 0;
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530696 uint8_t tid = std::get<0>(terminusInfo);
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600697
Andrew Jefferya330b2f2023-05-04 14:55:37 +0930698 auto instanceId = instanceIdDb.next(mctp_eid);
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600699 std::vector<uint8_t> requestMsg(
700 sizeof(pldm_msg_hdr) +
701 PLDM_GET_STATE_SENSOR_READINGS_REQ_BYTES);
702 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
703 auto rc = encode_get_state_sensor_readings_req(
704 instanceId, sensorId, sensorRearm, 0, request);
705
706 if (rc != PLDM_SUCCESS)
707 {
Andrew Jefferya330b2f2023-05-04 14:55:37 +0930708 instanceIdDb.free(mctp_eid, instanceId);
Riya Dixit49cfb132023-03-02 04:26:53 -0600709 error(
710 "Failed to encode_get_state_sensor_readings_req, rc = {RC}",
711 "RC", rc);
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600712 pldm::utils::reportError(
713 "xyz.openbmc_project.bmc.pldm.InternalFailure");
714 return;
715 }
716
Patrick Williams6da4f912023-05-10 07:50:53 -0500717 auto getStateSensorReadingRespHandler =
718 [=, this](mctp_eid_t /*eid*/, const pldm_msg* response,
719 size_t respMsgLen) {
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600720 if (response == nullptr || !respMsgLen)
721 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600722 error(
723 "Failed to receive response for getStateSensorReading command");
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600724 return;
725 }
726 std::array<get_sensor_state_field, 8> stateField{};
727 uint8_t completionCode = 0;
728 uint8_t comp_sensor_count = 0;
729
730 auto rc = decode_get_state_sensor_readings_resp(
731 response, respMsgLen, &completionCode,
732 &comp_sensor_count, stateField.data());
733
734 if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS)
735 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600736 error(
737 "Failed to decode_get_state_sensor_readings_resp, rc = {RC} cc = {CC}",
738 "RC", rc, "CC",
739 static_cast<unsigned>(completionCode));
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600740 pldm::utils::reportError(
741 "xyz.openbmc_project.bmc.pldm.InternalFailure");
742 }
743
744 uint8_t eventState;
745 uint8_t previousEventState;
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600746
RIYA DIXITbb5fda42022-09-27 06:48:08 -0500747 for (uint8_t sensorOffset = 0;
748 sensorOffset < comp_sensor_count; sensorOffset++)
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600749 {
RIYA DIXITbb5fda42022-09-27 06:48:08 -0500750 eventState = stateField[sensorOffset].present_state;
751 previousEventState =
752 stateField[sensorOffset].previous_state;
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600753
754 emitStateSensorEventSignal(tid, sensorId, sensorOffset,
755 eventState,
756 previousEventState);
757
758 SensorEntry sensorEntry{tid, sensorId};
759
760 pldm::pdr::EntityInfo entityInfo{};
761 pldm::pdr::CompositeSensorStates
762 compositeSensorStates{};
763
764 try
765 {
766 std::tie(entityInfo, compositeSensorStates) =
767 lookupSensorInfo(sensorEntry);
768 }
769 catch (const std::out_of_range& e)
770 {
771 try
772 {
773 sensorEntry.terminusID = PLDM_TID_RESERVED;
774 std::tie(entityInfo, compositeSensorStates) =
775 lookupSensorInfo(sensorEntry);
776 }
777 catch (const std::out_of_range& e)
778 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600779 error("No mapping for the events");
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600780 }
781 }
782
783 if (sensorOffset > compositeSensorStates.size())
784 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600785 error("Error Invalid data, Invalid sensor offset");
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600786 return;
787 }
788
789 const auto& possibleStates =
790 compositeSensorStates[sensorOffset];
791 if (possibleStates.find(eventState) ==
792 possibleStates.end())
793 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600794 error("Error invalid_data, Invalid event state");
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600795 return;
796 }
Patrick Williams6da4f912023-05-10 07:50:53 -0500797 const auto& [containerId, entityType,
798 entityInstance] = entityInfo;
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600799 pldm::responder::events::StateSensorEntry
800 stateSensorEntry{containerId, entityType,
801 entityInstance, sensorOffset};
802 handleStateSensorEvent(stateSensorEntry, eventState);
803 }
804 };
805
806 rc = handler->registerRequest(
807 mctp_eid, instanceId, PLDM_PLATFORM,
808 PLDM_GET_STATE_SENSOR_READINGS, std::move(requestMsg),
809 std::move(getStateSensorReadingRespHandler));
810
811 if (rc != PLDM_SUCCESS)
812 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600813 error(
814 "Failed to send request to get State sensor reading on Host");
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600815 }
816 }
817 }
818 }
819}
Pavithra Barithaya51efaf82020-04-02 02:42:27 -0500820} // namespace pldm