blob: 99bc13da46b60c1d09e442ea7f619f85721a27c4 [file] [log] [blame]
Pavithra Barithaya51efaf82020-04-02 02:42:27 -05001#include "host_pdr_handler.hpp"
2
George Liu682ee182020-12-25 15:24:33 +08003#include "libpldm/fru.h"
4#ifdef OEM_IBM
5#include "libpldm/fru_oem_ibm.h"
6#endif
7
8#include "custom_dbus.hpp"
9
Pavithra Barithayae8beb892020-04-14 23:24:25 -050010#include <assert.h>
11
Deepak Kodihalli87514cc2020-04-16 09:08:38 -050012#include <nlohmann/json.hpp>
Riya Dixit49cfb132023-03-02 04:26:53 -060013#include <phosphor-logging/lg2.hpp>
sampmisr6decfc12021-03-02 11:07:36 +053014#include <sdeventplus/clock.hpp>
15#include <sdeventplus/exception.hpp>
16#include <sdeventplus/source/io.hpp>
17#include <sdeventplus/source/time.hpp>
Deepak Kodihalli87514cc2020-04-16 09:08:38 -050018
George Liu6492f522020-06-16 10:34:05 +080019#include <fstream>
George Liu96af8cb2021-07-31 15:23:45 +080020#include <type_traits>
Pavithra Barithaya51efaf82020-04-02 02:42:27 -050021
Riya Dixit49cfb132023-03-02 04:26:53 -060022PHOSPHOR_LOG2_USING;
23
Pavithra Barithaya51efaf82020-04-02 02:42:27 -050024namespace pldm
25{
Brad Bishop5079ac42021-08-19 18:35:06 -040026using namespace pldm::responder::events;
Deepak Kodihalli6b1d1ca2020-04-27 07:24:51 -050027using namespace pldm::utils;
28using namespace sdbusplus::bus::match::rules;
Deepak Kodihalli87514cc2020-04-16 09:08:38 -050029using Json = nlohmann::json;
30namespace fs = std::filesystem;
George Liu682ee182020-12-25 15:24:33 +080031using namespace pldm::dbus;
Deepak Kodihalli87514cc2020-04-16 09:08:38 -050032constexpr auto fruJson = "host_frus.json";
33const Json emptyJson{};
34const std::vector<Json> emptyJsonList{};
35
Manojkiran Eda3ca40452021-10-04 22:51:37 +053036template <typename T>
37uint16_t extractTerminusHandle(std::vector<uint8_t>& pdr)
38{
39 T* var = nullptr;
40 if (std::is_same<T, pldm_pdr_fru_record_set>::value)
41 {
42 var = (T*)(pdr.data() + sizeof(pldm_pdr_hdr));
43 }
44 else
45 {
46 var = (T*)(pdr.data());
47 }
48 if (var != nullptr)
49 {
50 return var->terminus_handle;
51 }
52 return TERMINUS_HANDLE;
53}
54
George Liu96af8cb2021-07-31 15:23:45 +080055template <typename T>
56void updateContainerId(pldm_entity_association_tree* entityTree,
57 std::vector<uint8_t>& pdr)
58{
59 T* t = nullptr;
60 if (entityTree == nullptr)
61 {
62 return;
63 }
64 if (std::is_same<T, pldm_pdr_fru_record_set>::value)
65 {
66 t = (T*)(pdr.data() + sizeof(pldm_pdr_hdr));
67 }
68 else
69 {
70 t = (T*)(pdr.data());
71 }
72 if (t == nullptr)
73 {
74 return;
75 }
76
77 pldm_entity entity{t->entity_type, t->entity_instance, t->container_id};
78 auto node = pldm_entity_association_tree_find_with_locality(entityTree,
79 &entity, true);
80 if (node)
81 {
82 pldm_entity e = pldm_entity_extract(node);
83 t->container_id = e.entity_container_id;
84 }
85}
86
Tom Joseph74f27c72021-05-16 07:58:53 -070087HostPDRHandler::HostPDRHandler(
88 int mctp_fd, uint8_t mctp_eid, sdeventplus::Event& event, pldm_pdr* repo,
89 const std::string& eventsJsonsDir, pldm_entity_association_tree* entityTree,
Andrew Jefferya330b2f2023-05-04 14:55:37 +093090 pldm_entity_association_tree* bmcEntityTree,
91 pldm::InstanceIdDb& instanceIdDb,
Tom Josephe5268cd2021-09-07 13:04:03 +053092 pldm::requester::Handler<pldm::requester::Request>* handler) :
Deepak Kodihalli87514cc2020-04-16 09:08:38 -050093 mctp_fd(mctp_fd),
Pavithra Barithaya3aec9972020-12-14 01:55:44 -060094 mctp_eid(mctp_eid), event(event), repo(repo),
95 stateSensorHandler(eventsJsonsDir), entityTree(entityTree),
Andrew Jefferya330b2f2023-05-04 14:55:37 +093096 bmcEntityTree(bmcEntityTree), instanceIdDb(instanceIdDb), handler(handler)
Deepak Kodihalli87514cc2020-04-16 09:08:38 -050097{
George Liuacf2c8c2021-05-10 14:08:52 +080098 mergedHostParents = false;
Deepak Kodihalli87514cc2020-04-16 09:08:38 -050099 fs::path hostFruJson(fs::path(HOST_JSONS_DIR) / fruJson);
100 if (fs::exists(hostFruJson))
101 {
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500102 // Note parent entities for entities sent down by the host firmware.
103 // This will enable a merge of entity associations.
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500104 try
105 {
106 std::ifstream jsonFile(hostFruJson);
107 auto data = Json::parse(jsonFile, nullptr, false);
108 if (data.is_discarded())
109 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600110 error("Parsing Host FRU json file failed");
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500111 }
112 else
113 {
114 auto entities = data.value("entities", emptyJsonList);
115 for (auto& entity : entities)
116 {
117 EntityType entityType = entity.value("entity_type", 0);
118 auto parent = entity.value("parent", emptyJson);
119 pldm_entity p{};
120 p.entity_type = parent.value("entity_type", 0);
121 p.entity_instance_num = parent.value("entity_instance", 0);
122 parents.emplace(entityType, std::move(p));
123 }
124 }
125 }
126 catch (const std::exception& e)
127 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600128 error("Parsing Host FRU json file failed, exception = {ERR_EXCEP}",
129 "ERR_EXCEP", e.what());
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500130 }
131 }
Deepak Kodihalli6b1d1ca2020-04-27 07:24:51 -0500132
Patrick Williams84b790c2022-07-22 19:26:56 -0500133 hostOffMatch = std::make_unique<sdbusplus::bus::match_t>(
Deepak Kodihalli6b1d1ca2020-04-27 07:24:51 -0500134 pldm::utils::DBusHandler::getBus(),
135 propertiesChanged("/xyz/openbmc_project/state/host0",
136 "xyz.openbmc_project.State.Host"),
Patrick Williams84b790c2022-07-22 19:26:56 -0500137 [this, repo, entityTree, bmcEntityTree](sdbusplus::message_t& msg) {
Patrick Williams6da4f912023-05-10 07:50:53 -0500138 DbusChangedProps props{};
139 std::string intf;
140 msg.read(intf, props);
141 const auto itr = props.find("CurrentHostState");
142 if (itr != props.end())
143 {
144 PropertyValue value = itr->second;
145 auto propVal = std::get<std::string>(value);
146 if (propVal == "xyz.openbmc_project.State.Host.HostState.Off")
Deepak Kodihalli6b1d1ca2020-04-27 07:24:51 -0500147 {
Patrick Williams6da4f912023-05-10 07:50:53 -0500148 // Delete all the remote terminus information
149 std::erase_if(tlPDRInfo, [](const auto& item) {
150 auto const& [key, value] = item;
151 return key != TERMINUS_HANDLE;
152 });
153 pldm_pdr_remove_remote_pdrs(repo);
154 pldm_entity_association_tree_destroy_root(entityTree);
155 pldm_entity_association_tree_copy_root(bmcEntityTree,
156 entityTree);
157 this->sensorMap.clear();
158 this->responseReceived = false;
George Liuacf2c8c2021-05-10 14:08:52 +0800159 this->mergedHostParents = false;
Deepak Kodihalli6b1d1ca2020-04-27 07:24:51 -0500160 }
Patrick Williams6da4f912023-05-10 07:50:53 -0500161 }
Patrick Williamsa6756622023-10-20 11:19:15 -0500162 });
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500163}
164
Deepak Kodihalli7246e0c2020-07-08 06:40:18 -0500165void HostPDRHandler::fetchPDR(PDRRecordHandles&& recordHandles)
Pavithra Barithaya51efaf82020-04-02 02:42:27 -0500166{
Deepak Kodihalli8cb6f662020-04-10 02:55:43 -0500167 pdrRecordHandles.clear();
Pavithra Barithayaae5c97e2022-08-29 02:57:59 -0500168 modifiedPDRRecordHandles.clear();
169
170 if (isHostPdrModified)
171 {
172 modifiedPDRRecordHandles = std::move(recordHandles);
173 }
174 else
175 {
176 pdrRecordHandles = std::move(recordHandles);
177 }
Deepak Kodihalli8cb6f662020-04-10 02:55:43 -0500178
179 // Defer the actual fetch of PDRs from the host (by queuing the call on the
180 // main event loop). That way, we can respond to the platform event msg from
181 // the host firmware.
182 pdrFetchEvent = std::make_unique<sdeventplus::source::Defer>(
183 event, std::bind(std::mem_fn(&HostPDRHandler::_fetchPDR), this,
184 std::placeholders::_1));
185}
186
187void HostPDRHandler::_fetchPDR(sdeventplus::source::EventBase& /*source*/)
188{
Sampa Misrac0c79482021-06-02 08:01:54 -0500189 getHostPDR();
190}
191
192void HostPDRHandler::getHostPDR(uint32_t nextRecordHandle)
193{
Deepak Kodihalli8cb6f662020-04-10 02:55:43 -0500194 pdrFetchEvent.reset();
195
Pavithra Barithaya51efaf82020-04-02 02:42:27 -0500196 std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) +
197 PLDM_GET_PDR_REQ_BYTES);
198 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
Deepak Kodihalli7246e0c2020-07-08 06:40:18 -0500199 uint32_t recordHandle{};
Pavithra Barithayaae5c97e2022-08-29 02:57:59 -0500200 if (!nextRecordHandle && (!modifiedPDRRecordHandles.empty()) &&
201 isHostPdrModified)
Deepak Kodihalli7246e0c2020-07-08 06:40:18 -0500202 {
Pavithra Barithayaae5c97e2022-08-29 02:57:59 -0500203 recordHandle = modifiedPDRRecordHandles.front();
204 modifiedPDRRecordHandles.pop_front();
205 }
206 else if (!nextRecordHandle && (!pdrRecordHandles.empty()))
207 {
208 recordHandle = pdrRecordHandles.front();
209 pdrRecordHandles.pop_front();
Sampa Misrac0c79482021-06-02 08:01:54 -0500210 }
211 else
212 {
213 recordHandle = nextRecordHandle;
214 }
Andrew Jefferya330b2f2023-05-04 14:55:37 +0930215 auto instanceId = instanceIdDb.next(mctp_eid);
Sampa Misrac0c79482021-06-02 08:01:54 -0500216
Patrick Williams6da4f912023-05-10 07:50:53 -0500217 auto rc = encode_get_pdr_req(instanceId, recordHandle, 0,
218 PLDM_GET_FIRSTPART, UINT16_MAX, 0, request,
219 PLDM_GET_PDR_REQ_BYTES);
Sampa Misrac0c79482021-06-02 08:01:54 -0500220 if (rc != PLDM_SUCCESS)
221 {
Andrew Jefferya330b2f2023-05-04 14:55:37 +0930222 instanceIdDb.free(mctp_eid, instanceId);
Riya Dixit49cfb132023-03-02 04:26:53 -0600223 error("Failed to encode_get_pdr_req, rc = {RC}", "RC", rc);
Sampa Misrac0c79482021-06-02 08:01:54 -0500224 return;
225 }
Deepak Kodihalli7246e0c2020-07-08 06:40:18 -0500226
Sampa Misrac0c79482021-06-02 08:01:54 -0500227 rc = handler->registerRequest(
228 mctp_eid, instanceId, PLDM_PLATFORM, PLDM_GET_PDR,
229 std::move(requestMsg),
230 std::move(std::bind_front(&HostPDRHandler::processHostPDRs, this)));
231 if (rc)
Pavithra Barithaya51efaf82020-04-02 02:42:27 -0500232 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600233 error("Failed to send the GetPDR request to Host");
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500234 }
Pavithra Barithaya51efaf82020-04-02 02:42:27 -0500235}
236
Pavithra Barithaya3aec9972020-12-14 01:55:44 -0600237int HostPDRHandler::handleStateSensorEvent(const StateSensorEntry& entry,
238 pdr::EventState state)
239{
240 auto rc = stateSensorHandler.eventAction(entry, state);
241 if (rc != PLDM_SUCCESS)
242 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600243 error("Failed to fetch and update D-bus property, rc = {RC}", "RC", rc);
Pavithra Barithaya3aec9972020-12-14 01:55:44 -0600244 return rc;
245 }
246 return PLDM_SUCCESS;
247}
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500248
249void HostPDRHandler::mergeEntityAssociations(const std::vector<uint8_t>& pdr)
250{
251 size_t numEntities{};
252 pldm_entity* entities = nullptr;
253 bool merged = false;
254 auto entityPdr = reinterpret_cast<pldm_pdr_entity_association*>(
255 const_cast<uint8_t*>(pdr.data()) + sizeof(pldm_pdr_hdr));
256
257 pldm_entity_association_pdr_extract(pdr.data(), pdr.size(), &numEntities,
258 &entities);
George Liuacf2c8c2021-05-10 14:08:52 +0800259 if (numEntities > 0)
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500260 {
George Liuacf2c8c2021-05-10 14:08:52 +0800261 pldm_entity_node* pNode = nullptr;
262 if (!mergedHostParents)
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500263 {
George Liuacf2c8c2021-05-10 14:08:52 +0800264 pNode = pldm_entity_association_tree_find_with_locality(
265 entityTree, &entities[0], false);
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500266 }
George Liuacf2c8c2021-05-10 14:08:52 +0800267 else
268 {
269 pNode = pldm_entity_association_tree_find_with_locality(
270 entityTree, &entities[0], true);
271 }
272 if (!pNode)
273 {
274 return;
275 }
276
George Liudf9a6d32020-12-22 16:27:16 +0800277 Entities entityAssoc;
278 entityAssoc.push_back(pNode);
George Liuacf2c8c2021-05-10 14:08:52 +0800279 for (size_t i = 1; i < numEntities; ++i)
280 {
George Liudf9a6d32020-12-22 16:27:16 +0800281 auto node = pldm_entity_association_tree_add_entity(
George Liuacf2c8c2021-05-10 14:08:52 +0800282 entityTree, &entities[i], entities[i].entity_instance_num,
283 pNode, entityPdr->association_type, true, true, 0xFFFF);
284 merged = true;
George Liudf9a6d32020-12-22 16:27:16 +0800285 entityAssoc.push_back(node);
George Liuacf2c8c2021-05-10 14:08:52 +0800286 }
287
288 mergedHostParents = true;
George Liudf9a6d32020-12-22 16:27:16 +0800289 if (merged)
290 {
291 entityAssociations.push_back(entityAssoc);
292 }
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500293 }
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500294
295 if (merged)
296 {
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500297 // Update our PDR repo with the merged entity association PDRs
Sampa Misra719ed392021-06-04 05:15:13 -0500298 pldm_entity_node* node = nullptr;
299 pldm_find_entity_ref_in_tree(entityTree, entities[0], &node);
300 if (node == nullptr)
301 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600302 error("could not find referrence of the entity in the tree");
Sampa Misra719ed392021-06-04 05:15:13 -0500303 }
304 else
305 {
Andrew Jeffery1fd3c512023-07-03 13:02:03 +0930306 int rc = pldm_entity_association_pdr_add_from_node_check(
Manojkiran Eda3ca40452021-10-04 22:51:37 +0530307 node, repo, &entities, numEntities, true, TERMINUS_HANDLE);
Andrew Jeffery1fd3c512023-07-03 13:02:03 +0930308 if (rc)
309 {
310 error(
311 "Failed to add entity association PDR from node: {LIBPLDM_ERROR}",
312 "LIBPLDM_ERROR", rc);
313 }
Sampa Misra719ed392021-06-04 05:15:13 -0500314 }
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500315 }
Sampa Misra719ed392021-06-04 05:15:13 -0500316 free(entities);
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500317}
318
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500319void HostPDRHandler::sendPDRRepositoryChgEvent(std::vector<uint8_t>&& pdrTypes,
320 uint8_t eventDataFormat)
321{
322 assert(eventDataFormat == FORMAT_IS_PDR_HANDLES);
323
324 // Extract from the PDR repo record handles of PDRs we want the host
325 // to pull up.
326 std::vector<uint8_t> eventDataOps{PLDM_RECORDS_ADDED};
327 std::vector<uint8_t> numsOfChangeEntries(1);
328 std::vector<std::vector<ChangeEntry>> changeEntries(
329 numsOfChangeEntries.size());
330 for (auto pdrType : pdrTypes)
331 {
332 const pldm_pdr_record* record{};
333 do
334 {
335 record = pldm_pdr_find_record_by_type(repo, pdrType, record,
336 nullptr, nullptr);
337 if (record && pldm_pdr_record_is_remote(record))
338 {
339 changeEntries[0].push_back(
340 pldm_pdr_get_record_handle(repo, record));
341 }
342 } while (record);
343 }
344 if (changeEntries.empty())
345 {
346 return;
347 }
348 numsOfChangeEntries[0] = changeEntries[0].size();
349
350 // Encode PLDM platform event msg to indicate a PDR repo change.
351 size_t maxSize = PLDM_PDR_REPOSITORY_CHG_EVENT_MIN_LENGTH +
352 PLDM_PDR_REPOSITORY_CHANGE_RECORD_MIN_LENGTH +
353 changeEntries[0].size() * sizeof(uint32_t);
354 std::vector<uint8_t> eventDataVec{};
355 eventDataVec.resize(maxSize);
356 auto eventData =
357 reinterpret_cast<struct pldm_pdr_repository_chg_event_data*>(
358 eventDataVec.data());
359 size_t actualSize{};
360 auto firstEntry = changeEntries[0].data();
361 auto rc = encode_pldm_pdr_repository_chg_event_data(
362 eventDataFormat, 1, eventDataOps.data(), numsOfChangeEntries.data(),
363 &firstEntry, eventData, &actualSize, maxSize);
364 if (rc != PLDM_SUCCESS)
365 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600366 error("Failed to encode_pldm_pdr_repository_chg_event_data, rc = {RC}",
367 "RC", rc);
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500368 return;
369 }
Andrew Jefferya330b2f2023-05-04 14:55:37 +0930370 auto instanceId = instanceIdDb.next(mctp_eid);
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500371 std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) +
372 PLDM_PLATFORM_EVENT_MESSAGE_MIN_REQ_BYTES +
373 actualSize);
374 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
375 rc = encode_platform_event_message_req(
ArchanaKakani6c39c7a2022-12-05 04:36:35 -0600376 instanceId, 1, TERMINUS_ID, PLDM_PDR_REPOSITORY_CHG_EVENT,
377 eventDataVec.data(), actualSize, request,
Christian Geddes3bdb3c22020-05-01 14:55:39 -0500378 actualSize + PLDM_PLATFORM_EVENT_MESSAGE_MIN_REQ_BYTES);
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500379 if (rc != PLDM_SUCCESS)
380 {
Andrew Jefferya330b2f2023-05-04 14:55:37 +0930381 instanceIdDb.free(mctp_eid, instanceId);
Riya Dixit49cfb132023-03-02 04:26:53 -0600382 error("Failed to encode_platform_event_message_req, rc = {RC}", "RC",
383 rc);
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500384 return;
385 }
386
Patrick Williams6da4f912023-05-10 07:50:53 -0500387 auto platformEventMessageResponseHandler =
388 [](mctp_eid_t /*eid*/, const pldm_msg* response, size_t respMsgLen) {
Tom Joseph74f27c72021-05-16 07:58:53 -0700389 if (response == nullptr || !respMsgLen)
390 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600391 error(
392 "Failed to receive response for the PDR repository changed event");
Tom Joseph74f27c72021-05-16 07:58:53 -0700393 return;
394 }
395
396 uint8_t completionCode{};
397 uint8_t status{};
398 auto responsePtr = reinterpret_cast<const struct pldm_msg*>(response);
Pavithra Barithaya54b5a562021-09-27 06:07:10 -0500399 auto rc = decode_platform_event_message_resp(responsePtr, respMsgLen,
400 &completionCode, &status);
Sampa Misrac0c79482021-06-02 08:01:54 -0500401 if (rc || completionCode)
Tom Joseph74f27c72021-05-16 07:58:53 -0700402 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600403 error(
404 "Failed to decode_platform_event_message_resp: {RC}, cc = {CC}",
405 "RC", rc, "CC", static_cast<unsigned>(completionCode));
Tom Joseph74f27c72021-05-16 07:58:53 -0700406 }
407 };
408
Sampa Misrac0c79482021-06-02 08:01:54 -0500409 rc = handler->registerRequest(
Sampa Misra626c5652021-08-11 10:28:48 -0500410 mctp_eid, instanceId, PLDM_PLATFORM, PLDM_PLATFORM_EVENT_MESSAGE,
Tom Joseph74f27c72021-05-16 07:58:53 -0700411 std::move(requestMsg), std::move(platformEventMessageResponseHandler));
Sampa Misrac0c79482021-06-02 08:01:54 -0500412 if (rc)
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500413 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600414 error("Failed to send the PDR repository changed event request");
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500415 }
416}
417
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530418void HostPDRHandler::parseStateSensorPDRs(const PDRList& stateSensorPDRs)
Sampa Misra868c8792020-05-26 03:12:13 -0500419{
420 for (const auto& pdr : stateSensorPDRs)
421 {
422 SensorEntry sensorEntry{};
423 const auto& [terminusHandle, sensorID, sensorInfo] =
424 responder::pdr_utils::parseStateSensorPDR(pdr);
425 sensorEntry.sensorID = sensorID;
426 try
427 {
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530428 sensorEntry.terminusID = std::get<0>(tlPDRInfo.at(terminusHandle));
Sampa Misra868c8792020-05-26 03:12:13 -0500429 }
430 // If there is no mapping for terminusHandle assign the reserved TID
431 // value of 0xFF to indicate that.
432 catch (const std::out_of_range& e)
433 {
434 sensorEntry.terminusID = PLDM_TID_RESERVED;
435 }
436 sensorMap.emplace(sensorEntry, std::move(sensorInfo));
437 }
438}
439
Sampa Misrac0c79482021-06-02 08:01:54 -0500440void HostPDRHandler::processHostPDRs(mctp_eid_t /*eid*/,
441 const pldm_msg* response,
442 size_t respMsgLen)
443{
444 static bool merged = false;
445 static PDRList stateSensorPDRs{};
George Liu682ee182020-12-25 15:24:33 +0800446 static PDRList fruRecordSetPDRs{};
Sampa Misrac0c79482021-06-02 08:01:54 -0500447 uint32_t nextRecordHandle{};
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600448 uint8_t tlEid = 0;
449 bool tlValid = true;
450 uint32_t rh = 0;
451 uint16_t terminusHandle = 0;
Manojkiran Eda3ca40452021-10-04 22:51:37 +0530452 uint16_t pdrTerminusHandle = 0;
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600453 uint8_t tid = 0;
454
Sampa Misrac0c79482021-06-02 08:01:54 -0500455 uint8_t completionCode{};
456 uint32_t nextDataTransferHandle{};
457 uint8_t transferFlag{};
458 uint16_t respCount{};
459 uint8_t transferCRC{};
460 if (response == nullptr || !respMsgLen)
461 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600462 error("Failed to receive response for the GetPDR command");
Sampa Misrac0c79482021-06-02 08:01:54 -0500463 return;
464 }
465
466 auto rc = decode_get_pdr_resp(
467 response, respMsgLen /*- sizeof(pldm_msg_hdr)*/, &completionCode,
468 &nextRecordHandle, &nextDataTransferHandle, &transferFlag, &respCount,
469 nullptr, 0, &transferCRC);
470 std::vector<uint8_t> responsePDRMsg;
471 responsePDRMsg.resize(respMsgLen + sizeof(pldm_msg_hdr));
472 memcpy(responsePDRMsg.data(), response, respMsgLen + sizeof(pldm_msg_hdr));
Sampa Misrac0c79482021-06-02 08:01:54 -0500473 if (rc != PLDM_SUCCESS)
474 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600475 error("Failed to decode_get_pdr_resp, rc = {RC}", "RC", rc);
Sampa Misrac0c79482021-06-02 08:01:54 -0500476 return;
477 }
478 else
479 {
480 std::vector<uint8_t> pdr(respCount, 0);
481 rc = decode_get_pdr_resp(response, respMsgLen, &completionCode,
482 &nextRecordHandle, &nextDataTransferHandle,
483 &transferFlag, &respCount, pdr.data(),
484 respCount, &transferCRC);
485 if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS)
486 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600487 error("Failed to decode_get_pdr_resp: rc = {RC}, cc = {CC}", "RC",
488 rc, "CC", static_cast<unsigned>(completionCode));
Sampa Misrac0c79482021-06-02 08:01:54 -0500489 return;
490 }
491 else
492 {
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600493 // when nextRecordHandle is 0, we need the recordHandle of the last
494 // PDR and not 0-1.
495 if (!nextRecordHandle)
496 {
497 rh = nextRecordHandle;
498 }
499 else
500 {
501 rh = nextRecordHandle - 1;
502 }
503
Sampa Misrac0c79482021-06-02 08:01:54 -0500504 auto pdrHdr = reinterpret_cast<pldm_pdr_hdr*>(pdr.data());
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600505 if (!rh)
506 {
507 rh = pdrHdr->record_handle;
508 }
509
Sampa Misrac0c79482021-06-02 08:01:54 -0500510 if (pdrHdr->type == PLDM_PDR_ENTITY_ASSOCIATION)
511 {
512 this->mergeEntityAssociations(pdr);
513 merged = true;
514 }
515 else
516 {
517 if (pdrHdr->type == PLDM_TERMINUS_LOCATOR_PDR)
518 {
Manojkiran Eda3ca40452021-10-04 22:51:37 +0530519 pdrTerminusHandle =
520 extractTerminusHandle<pldm_terminus_locator_pdr>(pdr);
Sampa Misrac0c79482021-06-02 08:01:54 -0500521 auto tlpdr =
522 reinterpret_cast<const pldm_terminus_locator_pdr*>(
523 pdr.data());
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600524
525 terminusHandle = tlpdr->terminus_handle;
526 tid = tlpdr->tid;
527 auto terminus_locator_type = tlpdr->terminus_locator_type;
528 if (terminus_locator_type ==
529 PLDM_TERMINUS_LOCATOR_TYPE_MCTP_EID)
530 {
531 auto locatorValue = reinterpret_cast<
532 const pldm_terminus_locator_type_mctp_eid*>(
533 tlpdr->terminus_locator_value);
534 tlEid = static_cast<uint8_t>(locatorValue->eid);
535 }
536 if (tlpdr->validity == 0)
537 {
538 tlValid = false;
539 }
Pavithra Barithaya52aad392022-08-02 04:18:52 -0500540 for (const auto& terminusMap : tlPDRInfo)
541 {
542 if ((terminusHandle == (terminusMap.first)) &&
543 (get<1>(terminusMap.second) == tlEid) &&
544 (get<2>(terminusMap.second) == tlpdr->validity))
545 {
546 // TL PDR already present with same validity don't
547 // add the PDR to the repo just return
548 return;
549 }
550 }
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530551 tlPDRInfo.insert_or_assign(
552 tlpdr->terminus_handle,
553 std::make_tuple(tlpdr->tid, tlEid, tlpdr->validity));
Sampa Misrac0c79482021-06-02 08:01:54 -0500554 }
555 else if (pdrHdr->type == PLDM_STATE_SENSOR_PDR)
556 {
Manojkiran Eda3ca40452021-10-04 22:51:37 +0530557 pdrTerminusHandle =
558 extractTerminusHandle<pldm_state_sensor_pdr>(pdr);
George Liu96af8cb2021-07-31 15:23:45 +0800559 updateContainerId<pldm_state_sensor_pdr>(entityTree, pdr);
Sampa Misrac0c79482021-06-02 08:01:54 -0500560 stateSensorPDRs.emplace_back(pdr);
561 }
Manojkiran Eda3ca40452021-10-04 22:51:37 +0530562 else if (pdrHdr->type == PLDM_PDR_FRU_RECORD_SET)
563 {
564 pdrTerminusHandle =
565 extractTerminusHandle<pldm_pdr_fru_record_set>(pdr);
George Liu96af8cb2021-07-31 15:23:45 +0800566 updateContainerId<pldm_pdr_fru_record_set>(entityTree, pdr);
George Liu682ee182020-12-25 15:24:33 +0800567 fruRecordSetPDRs.emplace_back(pdr);
Manojkiran Eda3ca40452021-10-04 22:51:37 +0530568 }
569 else if (pdrHdr->type == PLDM_STATE_EFFECTER_PDR)
570 {
571 pdrTerminusHandle =
572 extractTerminusHandle<pldm_state_effecter_pdr>(pdr);
George Liu96af8cb2021-07-31 15:23:45 +0800573 updateContainerId<pldm_state_effecter_pdr>(entityTree, pdr);
Manojkiran Eda3ca40452021-10-04 22:51:37 +0530574 }
575 else if (pdrHdr->type == PLDM_NUMERIC_EFFECTER_PDR)
576 {
577 pdrTerminusHandle =
578 extractTerminusHandle<pldm_numeric_effecter_value_pdr>(
579 pdr);
George Liu96af8cb2021-07-31 15:23:45 +0800580 updateContainerId<pldm_numeric_effecter_value_pdr>(
581 entityTree, pdr);
Manojkiran Eda3ca40452021-10-04 22:51:37 +0530582 }
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600583 // if the TLPDR is invalid update the repo accordingly
584 if (!tlValid)
585 {
586 pldm_pdr_update_TL_pdr(repo, terminusHandle, tid, tlEid,
587 tlValid);
588 }
589 else
590 {
Andrew Jeffery64f37fe2023-07-03 15:41:13 +0930591 rc = pldm_pdr_add_check(repo, pdr.data(), respCount, true,
592 pdrTerminusHandle, &rh);
593 if (rc)
594 {
595 // pldm_pdr_add() assert()ed on failure to add a PDR.
596 throw std::runtime_error("Failed to add PDR");
597 }
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600598 }
Sampa Misrac0c79482021-06-02 08:01:54 -0500599 }
600 }
601 }
602 if (!nextRecordHandle)
603 {
George Liudf9a6d32020-12-22 16:27:16 +0800604 updateEntityAssociation(entityAssociations, entityTree, objPathMap);
605
Sampa Misrac0c79482021-06-02 08:01:54 -0500606 /*received last record*/
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530607 this->parseStateSensorPDRs(stateSensorPDRs);
George Liu682ee182020-12-25 15:24:33 +0800608 this->createDbusObjects(fruRecordSetPDRs);
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600609 if (isHostUp())
610 {
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530611 this->setHostSensorState(stateSensorPDRs);
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600612 }
Sampa Misrac0c79482021-06-02 08:01:54 -0500613 stateSensorPDRs.clear();
George Liu682ee182020-12-25 15:24:33 +0800614 fruRecordSetPDRs.clear();
George Liudf9a6d32020-12-22 16:27:16 +0800615 entityAssociations.clear();
616
Sampa Misrac0c79482021-06-02 08:01:54 -0500617 if (merged)
618 {
619 merged = false;
620 deferredPDRRepoChgEvent =
621 std::make_unique<sdeventplus::source::Defer>(
622 event,
623 std::bind(
624 std::mem_fn((&HostPDRHandler::_processPDRRepoChgEvent)),
625 this, std::placeholders::_1));
626 }
627 }
628 else
629 {
Pavithra Barithayaae5c97e2022-08-29 02:57:59 -0500630 if (modifiedPDRRecordHandles.empty() && isHostPdrModified)
631 {
632 isHostPdrModified = false;
633 }
634 else
635 {
636 deferredFetchPDREvent =
637 std::make_unique<sdeventplus::source::Defer>(
638 event,
639 std::bind(
640 std::mem_fn((&HostPDRHandler::_processFetchPDREvent)),
641 this, nextRecordHandle, std::placeholders::_1));
642 }
Sampa Misrac0c79482021-06-02 08:01:54 -0500643 }
644}
645
646void HostPDRHandler::_processPDRRepoChgEvent(
647 sdeventplus::source::EventBase& /*source */)
648{
649 deferredPDRRepoChgEvent.reset();
650 this->sendPDRRepositoryChgEvent(
651 std::move(std::vector<uint8_t>(1, PLDM_PDR_ENTITY_ASSOCIATION)),
652 FORMAT_IS_PDR_HANDLES);
653}
654
655void HostPDRHandler::_processFetchPDREvent(
656 uint32_t nextRecordHandle, sdeventplus::source::EventBase& /*source */)
657{
658 deferredFetchPDREvent.reset();
659 if (!this->pdrRecordHandles.empty())
660 {
661 nextRecordHandle = this->pdrRecordHandles.front();
662 this->pdrRecordHandles.pop_front();
663 }
Pavithra Barithayaae5c97e2022-08-29 02:57:59 -0500664 if (isHostPdrModified && (!this->modifiedPDRRecordHandles.empty()))
665 {
666 nextRecordHandle = this->modifiedPDRRecordHandles.front();
667 this->modifiedPDRRecordHandles.pop_front();
668 }
Sampa Misrac0c79482021-06-02 08:01:54 -0500669 this->getHostPDR(nextRecordHandle);
670}
671
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500672void HostPDRHandler::setHostFirmwareCondition()
sampmisr6decfc12021-03-02 11:07:36 +0530673{
sampmisr6decfc12021-03-02 11:07:36 +0530674 responseReceived = false;
Andrew Jefferya330b2f2023-05-04 14:55:37 +0930675 auto instanceId = instanceIdDb.next(mctp_eid);
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500676 std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) +
677 PLDM_GET_VERSION_REQ_BYTES);
678 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
679 auto rc = encode_get_version_req(instanceId, 0, PLDM_GET_FIRSTPART,
680 PLDM_BASE, request);
681 if (rc != PLDM_SUCCESS)
sampmisr6decfc12021-03-02 11:07:36 +0530682 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600683 error("GetPLDMVersion encode failure. PLDM error code = {RC}", "RC",
684 lg2::hex, rc);
Andrew Jefferya330b2f2023-05-04 14:55:37 +0930685 instanceIdDb.free(mctp_eid, instanceId);
sampmisr6decfc12021-03-02 11:07:36 +0530686 return;
687 }
688
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500689 auto getPLDMVersionHandler = [this](mctp_eid_t /*eid*/,
690 const pldm_msg* response,
691 size_t respMsgLen) {
692 if (response == nullptr || !respMsgLen)
sampmisr6decfc12021-03-02 11:07:36 +0530693 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600694 error(
695 "Failed to receive response for getPLDMVersion command, Host seems to be off");
sampmisr6decfc12021-03-02 11:07:36 +0530696 return;
697 }
Riya Dixit49cfb132023-03-02 04:26:53 -0600698 info("Getting the response. PLDM RC = {RC}", "RC", lg2::hex,
699 static_cast<uint16_t>(response->payload[0]));
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500700 this->responseReceived = true;
701 getHostPDR();
sampmisr6decfc12021-03-02 11:07:36 +0530702 };
Sampa Misraf9ba8c12021-08-06 00:33:47 -0500703 rc = handler->registerRequest(mctp_eid, instanceId, PLDM_BASE,
704 PLDM_GET_PLDM_VERSION, std::move(requestMsg),
705 std::move(getPLDMVersionHandler));
706 if (rc)
sampmisr6decfc12021-03-02 11:07:36 +0530707 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600708 error("Failed to discover Host state. Assuming Host as off");
sampmisr6decfc12021-03-02 11:07:36 +0530709 }
710}
711
712bool HostPDRHandler::isHostUp()
713{
714 return responseReceived;
715}
716
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530717void HostPDRHandler::setHostSensorState(const PDRList& stateSensorPDRs)
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600718{
719 for (const auto& stateSensorPDR : stateSensorPDRs)
720 {
721 auto pdr = reinterpret_cast<const pldm_state_sensor_pdr*>(
722 stateSensorPDR.data());
723
724 if (!pdr)
725 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600726 error("Failed to get State sensor PDR");
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600727 pldm::utils::reportError(
728 "xyz.openbmc_project.bmc.pldm.InternalFailure");
729 return;
730 }
731
732 uint16_t sensorId = pdr->sensor_id;
733
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530734 for (const auto& [terminusHandle, terminusInfo] : tlPDRInfo)
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600735 {
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530736 if (terminusHandle == pdr->terminus_handle)
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600737 {
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530738 if (std::get<2>(terminusInfo) == PLDM_TL_PDR_VALID)
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600739 {
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530740 mctp_eid = std::get<1>(terminusInfo);
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600741 }
742
743 bitfield8_t sensorRearm;
744 sensorRearm.byte = 0;
Manojkiran Eda60e1fe92021-10-08 15:58:16 +0530745 uint8_t tid = std::get<0>(terminusInfo);
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600746
Andrew Jefferya330b2f2023-05-04 14:55:37 +0930747 auto instanceId = instanceIdDb.next(mctp_eid);
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600748 std::vector<uint8_t> requestMsg(
749 sizeof(pldm_msg_hdr) +
750 PLDM_GET_STATE_SENSOR_READINGS_REQ_BYTES);
751 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
752 auto rc = encode_get_state_sensor_readings_req(
753 instanceId, sensorId, sensorRearm, 0, request);
754
755 if (rc != PLDM_SUCCESS)
756 {
Andrew Jefferya330b2f2023-05-04 14:55:37 +0930757 instanceIdDb.free(mctp_eid, instanceId);
Riya Dixit49cfb132023-03-02 04:26:53 -0600758 error(
759 "Failed to encode_get_state_sensor_readings_req, rc = {RC}",
760 "RC", rc);
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600761 pldm::utils::reportError(
762 "xyz.openbmc_project.bmc.pldm.InternalFailure");
763 return;
764 }
765
Patrick Williams6da4f912023-05-10 07:50:53 -0500766 auto getStateSensorReadingRespHandler =
767 [=, this](mctp_eid_t /*eid*/, const pldm_msg* response,
768 size_t respMsgLen) {
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600769 if (response == nullptr || !respMsgLen)
770 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600771 error(
772 "Failed to receive response for getStateSensorReading command");
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600773 return;
774 }
775 std::array<get_sensor_state_field, 8> stateField{};
776 uint8_t completionCode = 0;
777 uint8_t comp_sensor_count = 0;
778
779 auto rc = decode_get_state_sensor_readings_resp(
780 response, respMsgLen, &completionCode,
781 &comp_sensor_count, stateField.data());
782
783 if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS)
784 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600785 error(
786 "Failed to decode_get_state_sensor_readings_resp, rc = {RC} cc = {CC}",
787 "RC", rc, "CC",
788 static_cast<unsigned>(completionCode));
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600789 pldm::utils::reportError(
790 "xyz.openbmc_project.bmc.pldm.InternalFailure");
791 }
792
793 uint8_t eventState;
794 uint8_t previousEventState;
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600795
RIYA DIXITbb5fda42022-09-27 06:48:08 -0500796 for (uint8_t sensorOffset = 0;
797 sensorOffset < comp_sensor_count; sensorOffset++)
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600798 {
RIYA DIXITbb5fda42022-09-27 06:48:08 -0500799 eventState = stateField[sensorOffset].present_state;
800 previousEventState =
801 stateField[sensorOffset].previous_state;
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600802
803 emitStateSensorEventSignal(tid, sensorId, sensorOffset,
804 eventState,
805 previousEventState);
806
807 SensorEntry sensorEntry{tid, sensorId};
808
809 pldm::pdr::EntityInfo entityInfo{};
810 pldm::pdr::CompositeSensorStates
811 compositeSensorStates{};
812
813 try
814 {
815 std::tie(entityInfo, compositeSensorStates) =
816 lookupSensorInfo(sensorEntry);
817 }
818 catch (const std::out_of_range& e)
819 {
820 try
821 {
822 sensorEntry.terminusID = PLDM_TID_RESERVED;
823 std::tie(entityInfo, compositeSensorStates) =
824 lookupSensorInfo(sensorEntry);
825 }
826 catch (const std::out_of_range& e)
827 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600828 error("No mapping for the events");
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600829 }
830 }
831
832 if (sensorOffset > compositeSensorStates.size())
833 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600834 error("Error Invalid data, Invalid sensor offset");
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600835 return;
836 }
837
838 const auto& possibleStates =
839 compositeSensorStates[sensorOffset];
840 if (possibleStates.find(eventState) ==
841 possibleStates.end())
842 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600843 error("Error invalid_data, Invalid event state");
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600844 return;
845 }
Patrick Williams6da4f912023-05-10 07:50:53 -0500846 const auto& [containerId, entityType,
847 entityInstance] = entityInfo;
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600848 pldm::responder::events::StateSensorEntry
849 stateSensorEntry{containerId, entityType,
850 entityInstance, sensorOffset};
851 handleStateSensorEvent(stateSensorEntry, eventState);
852 }
853 };
854
855 rc = handler->registerRequest(
856 mctp_eid, instanceId, PLDM_PLATFORM,
857 PLDM_GET_STATE_SENSOR_READINGS, std::move(requestMsg),
858 std::move(getStateSensorReadingRespHandler));
859
860 if (rc != PLDM_SUCCESS)
861 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600862 error(
863 "Failed to send request to get State sensor reading on Host");
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600864 }
865 }
866 }
867 }
868}
George Liu682ee182020-12-25 15:24:33 +0800869
870void HostPDRHandler::getFRURecordTableMetadataByRemote(
871 const PDRList& fruRecordSetPDRs)
872{
873 auto instanceId = instanceIdDb.next(mctp_eid);
874 std::vector<uint8_t> requestMsg(
875 sizeof(pldm_msg_hdr) + PLDM_GET_FRU_RECORD_TABLE_METADATA_REQ_BYTES);
876
877 // GetFruRecordTableMetadata
878 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
879 auto rc = encode_get_fru_record_table_metadata_req(
880 instanceId, request, requestMsg.size() - sizeof(pldm_msg_hdr));
881 if (rc != PLDM_SUCCESS)
882 {
883 instanceIdDb.free(mctp_eid, instanceId);
884 lg2::error(
885 "Failed to encode_get_fru_record_table_metadata_req, rc = {RC}",
886 "RC", lg2::hex, rc);
887 return;
888 }
889
890 auto getFruRecordTableMetadataResponseHandler =
891 [this, fruRecordSetPDRs](mctp_eid_t /*eid*/, const pldm_msg* response,
892 size_t respMsgLen) {
893 if (response == nullptr || !respMsgLen)
894 {
895 lg2::error(
896 "Failed to receive response for the Get FRU Record Table Metadata");
897 return;
898 }
899
900 uint8_t cc = 0;
901 uint8_t fru_data_major_version, fru_data_minor_version;
902 uint32_t fru_table_maximum_size, fru_table_length;
903 uint16_t total_record_set_identifiers;
904 uint16_t total;
905 uint32_t checksum;
906
907 auto rc = decode_get_fru_record_table_metadata_resp(
908 response, respMsgLen, &cc, &fru_data_major_version,
909 &fru_data_minor_version, &fru_table_maximum_size, &fru_table_length,
910 &total_record_set_identifiers, &total, &checksum);
911
912 if (rc != PLDM_SUCCESS || cc != PLDM_SUCCESS)
913 {
914 lg2::error(
915 "Faile to decode get fru record table metadata resp, Message Error: {RC}, cc: {CC}",
916 "RC", lg2::hex, rc, "CC", cc);
917 return;
918 }
919
920 // pass total to getFRURecordTableByRemote
921 this->getFRURecordTableByRemote(fruRecordSetPDRs, total);
922 };
923
924 rc = handler->registerRequest(
925 mctp_eid, instanceId, PLDM_FRU, PLDM_GET_FRU_RECORD_TABLE_METADATA,
926 std::move(requestMsg),
927 std::move(getFruRecordTableMetadataResponseHandler));
928 if (rc != PLDM_SUCCESS)
929 {
930 lg2::error("Failed to send the the Set State Effecter States request");
931 }
932
933 return;
934}
935
936void HostPDRHandler::getFRURecordTableByRemote(const PDRList& fruRecordSetPDRs,
937 uint16_t totalTableRecords)
938{
939 fruRecordData.clear();
940
941 if (!totalTableRecords)
942 {
943 lg2::error("Failed to get fru record table");
944 return;
945 }
946
947 auto instanceId = instanceIdDb.next(mctp_eid);
948 std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) +
949 PLDM_GET_FRU_RECORD_TABLE_REQ_BYTES);
950
951 // send the getFruRecordTable command
952 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
953 auto rc = encode_get_fru_record_table_req(
954 instanceId, 0, PLDM_GET_FIRSTPART, request,
955 requestMsg.size() - sizeof(pldm_msg_hdr));
956 if (rc != PLDM_SUCCESS)
957 {
958 instanceIdDb.free(mctp_eid, instanceId);
959 lg2::error("Failed to encode_get_fru_record_table_req, rc = {RC}", "RC",
960 lg2::hex, rc);
961 return;
962 }
963
964 auto getFruRecordTableResponseHandler =
965 [totalTableRecords, this, fruRecordSetPDRs](
966 mctp_eid_t /*eid*/, const pldm_msg* response, size_t respMsgLen) {
967 if (response == nullptr || !respMsgLen)
968 {
969 lg2::error(
970 "Failed to receive response for the Get FRU Record Table");
971 return;
972 }
973
974 uint8_t cc = 0;
975 uint32_t next_data_transfer_handle = 0;
976 uint8_t transfer_flag = 0;
977 size_t fru_record_table_length = 0;
978 std::vector<uint8_t> fru_record_table_data(respMsgLen -
979 sizeof(pldm_msg_hdr));
980 auto responsePtr = reinterpret_cast<const struct pldm_msg*>(response);
981 auto rc = decode_get_fru_record_table_resp(
982 responsePtr, respMsgLen - sizeof(pldm_msg_hdr), &cc,
983 &next_data_transfer_handle, &transfer_flag,
984 fru_record_table_data.data(), &fru_record_table_length);
985
986 if (rc != PLDM_SUCCESS || cc != PLDM_SUCCESS)
987 {
988 lg2::error(
989 "Failed to decode get fru record table resp, Message Error: {RC}, cc: {CC}",
990 "RC", lg2::hex, rc, "CC", cc);
991 return;
992 }
993
994 fruRecordData = responder::pdr_utils::parseFruRecordTable(
995 fru_record_table_data.data(), fru_record_table_length);
996
997 if (totalTableRecords != fruRecordData.size())
998 {
999 fruRecordData.clear();
1000
1001 lg2::error("failed to parse fru recrod data format.");
1002 return;
1003 }
1004
1005 this->setFRUDataOnDBus(fruRecordSetPDRs, fruRecordData);
1006 };
1007
1008 rc = handler->registerRequest(
1009 mctp_eid, instanceId, PLDM_FRU, PLDM_GET_FRU_RECORD_TABLE,
1010 std::move(requestMsg), std::move(getFruRecordTableResponseHandler));
1011 if (rc != PLDM_SUCCESS)
1012 {
1013 lg2::error("Failed to send the the Set State Effecter States request");
1014 }
1015}
1016
1017std::optional<uint16_t> HostPDRHandler::getRSI(const PDRList& fruRecordSetPDRs,
1018 const pldm_entity& entity)
1019{
1020 for (const auto& pdr : fruRecordSetPDRs)
1021 {
1022 auto fruPdr = reinterpret_cast<const pldm_pdr_fru_record_set*>(
1023 const_cast<uint8_t*>(pdr.data()) + sizeof(pldm_pdr_hdr));
1024
1025 if (fruPdr->entity_type == entity.entity_type &&
Sagar Srinivasebf8bb52023-10-06 01:15:55 -05001026 fruPdr->entity_instance == entity.entity_instance_num &&
1027 fruPdr->container_id == entity.entity_container_id)
George Liu682ee182020-12-25 15:24:33 +08001028 {
1029 return fruPdr->fru_rsi;
1030 }
1031 }
1032
1033 return std::nullopt;
1034}
1035
1036void HostPDRHandler::setFRUDataOnDBus(
Patrick Williamsd310f822023-10-07 19:01:19 -05001037 [[maybe_unused]] const PDRList& fruRecordSetPDRs,
1038 [[maybe_unused]] const std::vector<
1039 responder::pdr_utils::FruRecordDataFormat>& fruRecordData)
George Liu682ee182020-12-25 15:24:33 +08001040{
Patrick Williamsd310f822023-10-07 19:01:19 -05001041#ifdef OEM_IBM
George Liu682ee182020-12-25 15:24:33 +08001042 for (const auto& entity : objPathMap)
1043 {
1044 pldm_entity node = pldm_entity_extract(entity.second);
1045 auto fruRSI = getRSI(fruRecordSetPDRs, node);
1046
1047 for (const auto& data : fruRecordData)
1048 {
1049 if (!fruRSI || *fruRSI != data.fruRSI)
1050 {
1051 continue;
1052 }
1053
1054 if (data.fruRecType == PLDM_FRU_RECORD_TYPE_OEM)
1055 {
1056 for (const auto& tlv : data.fruTLV)
1057 {
1058 if (tlv.fruFieldType ==
1059 PLDM_OEM_FRU_FIELD_TYPE_LOCATION_CODE)
1060 {
1061 CustomDBus::getCustomDBus().setLocationCode(
1062 entity.first,
1063 std::string(reinterpret_cast<const char*>(
1064 tlv.fruFieldValue.data()),
1065 tlv.fruFieldLen));
1066 }
1067 }
1068 }
1069 }
1070 }
Patrick Williamsd310f822023-10-07 19:01:19 -05001071#endif
George Liu682ee182020-12-25 15:24:33 +08001072}
1073void HostPDRHandler::createDbusObjects(const PDRList& fruRecordSetPDRs)
1074{
1075 // TODO: Creating and Refreshing dbus hosted by remote PLDM entity Fru PDRs
1076
1077 getFRURecordTableMetadataByRemote(fruRecordSetPDRs);
1078}
1079
Pavithra Barithaya51efaf82020-04-02 02:42:27 -05001080} // namespace pldm