blob: 8d0cda0672de1fd8463106e11b7c613dee57a674 [file] [log] [blame]
Deepak Kodihalli557dfb02019-05-12 13:11:17 +05301
2#include "platform.hpp"
3
George Liu456c9a22020-01-13 11:36:22 +08004#include "pdr_numeric_effecter.hpp"
George Liua2870722020-02-11 11:09:30 +08005#include "pdr_state_effecter.hpp"
George Liu83409572019-12-24 18:42:54 +08006#include "utils.hpp"
7
Deepak Kodihalli557dfb02019-05-12 13:11:17 +05308namespace pldm
9{
Deepak Kodihalli557dfb02019-05-12 13:11:17 +053010namespace responder
11{
Sampa Misraa2fa0702019-05-31 01:28:55 -050012namespace platform
13{
14
Deepak Kodihallic682fe22020-03-04 00:42:54 -060015using InternalFailure =
16 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
17
George Liu1ec85d42020-02-12 16:05:32 +080018static const Json empty{};
19
Zahed Hossain75330f32020-03-24 02:15:03 -050020using EventEntryMap = std::map<EventEntry, DBusInfo>;
21
22const EventEntryMap eventEntryMap = {
23 {
24 0x01010007, // SensorID for VMI Port 0 ipv4 = 7, SensorOffset for the
25 // State Set ID 15 = 1 & PLDM State Set Enumeration List = 1
26 // (Valid Configuration)
27 {"/xyz/openbmc_project/network/vmi/intf0/ipv4/addr0",
28 "xyz.openbmc_project.Object.Enable", "Enabled", "bool", true},
29 },
30 {
31 0x02010007, // SensorID for VMI Port 0 ipv4 = 7, SensorOffset for the
32 // State Set ID 15 = 1 & PLDM State Set Enumeration List = 2
33 // (Invalid Configuration)
34 {"/xyz/openbmc_project/network/vmi/intf0/ipv4/addr0",
35 "xyz.openbmc_project.Object.Enable", "Enabled", "bool", false},
36 },
37 {
38 0x01010008, // SensorID for VMI Port 1 ipv4 = 8, SensorOffset for the
39 // State Set ID 15 = 1 & PLDM State Set Enumeration List = 1
40 // (Valid Configuration)
41 {"/xyz/openbmc_project/network/vmi/intf1/ipv4/addr0",
42 "xyz.openbmc_project.Object.Enable", "Enabled", "bool", true},
43 },
44 {
45 0x02010008, // SensorID for VMI Port 1 ipv4 = 8, SensorOffset for the
46 // State Set ID 15 = 1 & PLDM State Set Enumeration List = 2
47 // (Invalid Configuration)
48 {"/xyz/openbmc_project/network/vmi/intf1/ipv4/addr0",
49 "xyz.openbmc_project.Object.Enable", "Enabled", "bool", false},
50 }};
51
George Liua2870722020-02-11 11:09:30 +080052void Handler::addDbusObjMaps(
53 uint16_t effecterId,
54 std::tuple<pdr_utils::DbusMappings, pdr_utils::DbusValMaps> dbusObj)
George Liu1ec85d42020-02-12 16:05:32 +080055{
56 dbusObjMaps.emplace(effecterId, dbusObj);
57}
58
George Liua2870722020-02-11 11:09:30 +080059const std::tuple<pdr_utils::DbusMappings, pdr_utils::DbusValMaps>&
George Liu1ec85d42020-02-12 16:05:32 +080060 Handler::getDbusObjMaps(uint16_t effecterId) const
61{
62 return dbusObjMaps.at(effecterId);
63}
64
Deepak Kodihallic682fe22020-03-04 00:42:54 -060065void Handler::generate(const std::string& dir, Repo& repo)
66{
67 // A map of PDR type to a lambda that handles creation of that PDR type.
68 // The lambda essentially would parse the platform specific PDR JSONs to
69 // generate the PDR structures. This function iterates through the map to
70 // invoke all lambdas, so that all PDR types can be created.
George Liua2870722020-02-11 11:09:30 +080071
72 const std::map<Type, generatePDR> generateHandlers = {
73 {PLDM_STATE_EFFECTER_PDR,
74 [this](const auto& json, RepoInterface& repo) {
75 pdr_state_effecter::generateStateEffecterPDR<Handler>(json, *this,
76 repo);
George Liu456c9a22020-01-13 11:36:22 +080077 }},
78 {PLDM_NUMERIC_EFFECTER_PDR,
79 [this](const auto& json, RepoInterface& repo) {
80 pdr_numeric_effecter::generateNumericEffecterPDR<Handler>(
81 json, *this, repo);
George Liua2870722020-02-11 11:09:30 +080082 }}};
Deepak Kodihallic682fe22020-03-04 00:42:54 -060083
84 Type pdrType{};
85 for (const auto& dirEntry : fs::directory_iterator(dir))
86 {
87 try
88 {
89 auto json = readJson(dirEntry.path().string());
90 if (!json.empty())
91 {
George Liu1ec85d42020-02-12 16:05:32 +080092 auto effecterPDRs = json.value("effecterPDRs", empty);
93 for (const auto& effecter : effecterPDRs)
94 {
95 pdrType = effecter.value("pdrType", 0);
George Liua2870722020-02-11 11:09:30 +080096 generateHandlers.at(pdrType)(effecter, repo);
George Liu1ec85d42020-02-12 16:05:32 +080097 }
Deepak Kodihallic682fe22020-03-04 00:42:54 -060098 }
99 }
100 catch (const InternalFailure& e)
101 {
102 std::cerr << "PDR config directory does not exist or empty, TYPE= "
103 << pdrType << "PATH= " << dirEntry
104 << " ERROR=" << e.what() << "\n";
105 }
106 catch (const Json::exception& e)
107 {
108 std::cerr << "Failed parsing PDR JSON file, TYPE= " << pdrType
109 << " ERROR=" << e.what() << "\n";
110 pldm::utils::reportError(
111 "xyz.openbmc_project.bmc.pldm.InternalFailure");
112 }
113 catch (const std::exception& e)
114 {
115 std::cerr << "Failed parsing PDR JSON file, TYPE= " << pdrType
116 << " ERROR=" << e.what() << "\n";
117 pldm::utils::reportError(
118 "xyz.openbmc_project.bmc.pldm.InternalFailure");
119 }
120 }
121}
Deepak Kodihalli557dfb02019-05-12 13:11:17 +0530122
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600123Response Handler::getPDR(const pldm_msg* request, size_t payloadLength)
Deepak Kodihalli557dfb02019-05-12 13:11:17 +0530124{
125 Response response(sizeof(pldm_msg_hdr) + PLDM_GET_PDR_MIN_RESP_BYTES, 0);
126 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
127
128 if (payloadLength != PLDM_GET_PDR_REQ_BYTES)
129 {
George Liufb8611d2019-12-06 10:14:15 +0800130 return CmdHandler::ccOnlyResponse(request, PLDM_ERROR_INVALID_LENGTH);
Deepak Kodihalli557dfb02019-05-12 13:11:17 +0530131 }
132
133 uint32_t recordHandle{};
134 uint32_t dataTransferHandle{};
135 uint8_t transferOpFlag{};
136 uint16_t reqSizeBytes{};
137 uint16_t recordChangeNum{};
138
George Liufb8611d2019-12-06 10:14:15 +0800139 auto rc = decode_get_pdr_req(request, payloadLength, &recordHandle,
140 &dataTransferHandle, &transferOpFlag,
141 &reqSizeBytes, &recordChangeNum);
142 if (rc != PLDM_SUCCESS)
143 {
144 return CmdHandler::ccOnlyResponse(request, rc);
145 }
Deepak Kodihalli557dfb02019-05-12 13:11:17 +0530146
Deepak Kodihalli557dfb02019-05-12 13:11:17 +0530147 uint16_t respSizeBytes{};
148 uint8_t* recordData = nullptr;
149 try
150 {
George Liue53193f2020-02-24 09:23:26 +0800151 pdr_utils::PdrEntry e;
152 auto record = pdr::getRecordByHandle(pdrRepo, recordHandle, e);
153 if (record == NULL)
154 {
155 return CmdHandler::ccOnlyResponse(
156 request, PLDM_PLATFORM_INVALID_RECORD_HANDLE);
157 }
158
Deepak Kodihalli557dfb02019-05-12 13:11:17 +0530159 if (reqSizeBytes)
160 {
George Liue53193f2020-02-24 09:23:26 +0800161 respSizeBytes = e.size;
Deepak Kodihalli557dfb02019-05-12 13:11:17 +0530162 if (respSizeBytes > reqSizeBytes)
163 {
164 respSizeBytes = reqSizeBytes;
165 }
George Liue53193f2020-02-24 09:23:26 +0800166 recordData = e.data;
Deepak Kodihalli557dfb02019-05-12 13:11:17 +0530167 }
168 response.resize(sizeof(pldm_msg_hdr) + PLDM_GET_PDR_MIN_RESP_BYTES +
169 respSizeBytes,
170 0);
171 responsePtr = reinterpret_cast<pldm_msg*>(response.data());
Deepak Kodihalli22b5a7d2020-03-17 23:28:41 -0500172 rc = encode_get_pdr_resp(
173 request->hdr.instance_id, PLDM_SUCCESS, e.handle.nextRecordHandle,
174 0, PLDM_START_AND_END, respSizeBytes, recordData, 0, responsePtr);
George Liufb8611d2019-12-06 10:14:15 +0800175 if (rc != PLDM_SUCCESS)
176 {
177 return ccOnlyResponse(request, rc);
178 }
Deepak Kodihalli557dfb02019-05-12 13:11:17 +0530179 }
Deepak Kodihalli557dfb02019-05-12 13:11:17 +0530180 catch (const std::exception& e)
181 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600182 std::cerr << "Error accessing PDR, HANDLE=" << recordHandle
183 << " ERROR=" << e.what() << "\n";
George Liufb8611d2019-12-06 10:14:15 +0800184 return CmdHandler::ccOnlyResponse(request, PLDM_ERROR);
Deepak Kodihalli557dfb02019-05-12 13:11:17 +0530185 }
186 return response;
187}
188
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600189Response Handler::setStateEffecterStates(const pldm_msg* request,
190 size_t payloadLength)
Sampa Misraa2fa0702019-05-31 01:28:55 -0500191{
192 Response response(
193 sizeof(pldm_msg_hdr) + PLDM_SET_STATE_EFFECTER_STATES_RESP_BYTES, 0);
194 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
195 uint16_t effecterId;
196 uint8_t compEffecterCnt;
197 constexpr auto maxCompositeEffecterCnt = 8;
198 std::vector<set_effecter_state_field> stateField(maxCompositeEffecterCnt,
199 {0, 0});
200
201 if ((payloadLength > PLDM_SET_STATE_EFFECTER_STATES_REQ_BYTES) ||
202 (payloadLength < sizeof(effecterId) + sizeof(compEffecterCnt) +
203 sizeof(set_effecter_state_field)))
204 {
George Liufb8611d2019-12-06 10:14:15 +0800205 return CmdHandler::ccOnlyResponse(request, PLDM_ERROR_INVALID_LENGTH);
Sampa Misraa2fa0702019-05-31 01:28:55 -0500206 }
207
208 int rc = decode_set_state_effecter_states_req(request, payloadLength,
209 &effecterId, &compEffecterCnt,
210 stateField.data());
211
George Liufb8611d2019-12-06 10:14:15 +0800212 if (rc != PLDM_SUCCESS)
Sampa Misraa2fa0702019-05-31 01:28:55 -0500213 {
George Liufb8611d2019-12-06 10:14:15 +0800214 return CmdHandler::ccOnlyResponse(request, rc);
Sampa Misraa2fa0702019-05-31 01:28:55 -0500215 }
216
George Liufb8611d2019-12-06 10:14:15 +0800217 stateField.resize(compEffecterCnt);
218 const pldm::utils::DBusHandler dBusIntf;
219 rc = setStateEffecterStatesHandler<pldm::utils::DBusHandler>(
220 dBusIntf, effecterId, stateField);
221 if (rc != PLDM_SUCCESS)
222 {
223 return CmdHandler::ccOnlyResponse(request, rc);
224 }
225
226 rc = encode_set_state_effecter_states_resp(request->hdr.instance_id, rc,
227 responsePtr);
228 if (rc != PLDM_SUCCESS)
229 {
230 return ccOnlyResponse(request, rc);
231 }
232
Sampa Misraa2fa0702019-05-31 01:28:55 -0500233 return response;
234}
235
Tom Joseph56e45c52020-03-16 10:01:45 +0530236Response Handler::platformEventMessage(const pldm_msg* request,
237 size_t payloadLength)
238{
239 uint8_t formatVersion{};
240 uint8_t tid{};
241 uint8_t eventClass{};
242 size_t offset{};
243
244 auto rc = decode_platform_event_message_req(
245 request, payloadLength, &formatVersion, &tid, &eventClass, &offset);
246 if (rc != PLDM_SUCCESS)
247 {
248 return CmdHandler::ccOnlyResponse(request, rc);
249 }
250
251 try
252 {
253 const auto& handlers = eventHandlers.at(eventClass);
254 for (const auto& handler : handlers)
255 {
256 auto rc =
257 handler(request, payloadLength, formatVersion, tid, offset);
258 if (rc != PLDM_SUCCESS)
259 {
260 return CmdHandler::ccOnlyResponse(request, rc);
261 }
262 }
263 }
264 catch (const std::out_of_range& e)
265 {
266 return CmdHandler::ccOnlyResponse(request, PLDM_ERROR_INVALID_DATA);
267 }
268
269 Response response(
270 sizeof(pldm_msg_hdr) + PLDM_PLATFORM_EVENT_MESSAGE_RESP_BYTES, 0);
271 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
272
273 rc = encode_platform_event_message_resp(request->hdr.instance_id, rc,
274 PLDM_EVENT_NO_LOGGING, responsePtr);
275 if (rc != PLDM_SUCCESS)
276 {
277 return ccOnlyResponse(request, rc);
278 }
279
280 return response;
281}
282
283int Handler::sensorEvent(const pldm_msg* request, size_t payloadLength,
284 uint8_t /*formatVersion*/, uint8_t /*tid*/,
285 size_t eventDataOffset)
286{
287 uint16_t sensorId{};
288 uint8_t eventClass{};
289 size_t eventClassDataOffset{};
290 auto eventData =
291 reinterpret_cast<const uint8_t*>(request->payload) + eventDataOffset;
292 auto eventDataSize = payloadLength - eventDataOffset;
293
294 auto rc = decode_sensor_event_data(eventData, eventDataSize, &sensorId,
295 &eventClass, &eventClassDataOffset);
296 if (rc != PLDM_SUCCESS)
297 {
298 return rc;
299 }
300
Zahed Hossain75330f32020-03-24 02:15:03 -0500301 auto eventClassData = reinterpret_cast<const uint8_t*>(request->payload) +
302 eventDataOffset + eventClassDataOffset;
303 auto eventClassDataSize =
304 payloadLength - eventDataOffset - eventClassDataOffset;
305
Tom Joseph56e45c52020-03-16 10:01:45 +0530306 if (eventClass == PLDM_STATE_SENSOR_STATE)
307 {
308 uint8_t sensorOffset{};
309 uint8_t eventState{};
310 uint8_t previousEventState{};
311
Zahed Hossain75330f32020-03-24 02:15:03 -0500312 rc = decode_state_sensor_data(eventClassData, eventClassDataSize,
Tom Joseph56e45c52020-03-16 10:01:45 +0530313 &sensorOffset, &eventState,
314 &previousEventState);
Zahed Hossain75330f32020-03-24 02:15:03 -0500315 if (rc != PLDM_SUCCESS)
316 {
317 return PLDM_ERROR;
318 }
319
320 rc = setSensorEventData(sensorId, sensorOffset, eventState);
321
322 if (rc != PLDM_SUCCESS)
323 {
324 return PLDM_ERROR;
325 }
Tom Joseph56e45c52020-03-16 10:01:45 +0530326 }
327 else
328 {
329 return PLDM_ERROR_INVALID_DATA;
330 }
331
332 return PLDM_SUCCESS;
333}
334
Zahed Hossain75330f32020-03-24 02:15:03 -0500335int Handler::setSensorEventData(uint16_t sensorId, uint8_t sensorOffset,
336 uint8_t eventState)
337{
338 EventEntry eventEntry = ((static_cast<uint32_t>(eventState)) << 24) +
339 ((static_cast<uint32_t>(sensorOffset)) << 16) +
340 sensorId;
341 auto iter = eventEntryMap.find(eventEntry);
342 if (iter == eventEntryMap.end())
343 {
344 return PLDM_SUCCESS;
345 }
346
347 const auto& dBusInfo = iter->second;
348 try
349 {
350 pldm::utils::DBusMapping dbusMapping{
351 dBusInfo.dBusValues.objectPath, dBusInfo.dBusValues.interface,
352 dBusInfo.dBusValues.propertyName, dBusInfo.dBusValues.propertyType};
353 pldm::utils::DBusHandler().setDbusProperty(dbusMapping,
354 dBusInfo.dBusPropertyValue);
355 }
356 catch (std::exception& e)
357 {
358
359 std::cerr
360 << "Error Setting dbus property,SensorID=" << eventEntry
361 << "DBusInfo=" << dBusInfo.dBusValues.objectPath
362 << dBusInfo.dBusValues.interface << dBusInfo.dBusValues.propertyName
363 << "ERROR=" << e.what() << "\n";
364 return PLDM_ERROR;
365 }
366 return PLDM_SUCCESS;
367}
368
Deepak Kodihalli8cb6f662020-04-10 02:55:43 -0500369int Handler::pldmPDRRepositoryChgEvent(const pldm_msg* request,
370 size_t payloadLength,
371 uint8_t /*formatVersion*/,
372 uint8_t /*tid*/, size_t eventDataOffset)
373{
374 uint8_t eventDataFormat{};
375 uint8_t numberOfChangeRecords{};
376 size_t dataOffset{};
377
378 auto eventData =
379 reinterpret_cast<const uint8_t*>(request->payload) + eventDataOffset;
380 auto eventDataSize = payloadLength - eventDataOffset;
381
382 auto rc = decode_pldm_pdr_repository_chg_event_data(
383 eventData, eventDataSize, &eventDataFormat, &numberOfChangeRecords,
384 &dataOffset);
385 if (rc != PLDM_SUCCESS)
386 {
387 return rc;
388 }
389
390 PDRRecordHandles pdrRecordHandles;
391 if (eventDataFormat == FORMAT_IS_PDR_HANDLES)
392 {
393 uint8_t eventDataOperation{};
394 uint8_t numberOfChangeEntries{};
395
396 auto changeRecordData = eventData + dataOffset;
397 auto changeRecordDataSize = eventDataSize - dataOffset;
398
399 while (changeRecordDataSize)
400 {
401 rc = decode_pldm_pdr_repository_change_record_data(
402 changeRecordData, changeRecordDataSize, &eventDataOperation,
403 &numberOfChangeEntries, &dataOffset);
404
405 if (rc != PLDM_SUCCESS)
406 {
407 return rc;
408 }
409
410 if (eventDataOperation == PLDM_RECORDS_ADDED)
411 {
412 rc = getPDRRecordHandles(
413 reinterpret_cast<const ChangeEntry*>(changeRecordData +
414 dataOffset),
415 changeRecordDataSize - dataOffset,
416 static_cast<size_t>(numberOfChangeEntries),
417 pdrRecordHandles);
418
419 if (rc != PLDM_SUCCESS)
420 {
421 return rc;
422 }
423 }
424
425 changeRecordData +=
426 dataOffset + (numberOfChangeEntries * sizeof(ChangeEntry));
427 changeRecordDataSize -=
428 dataOffset + (numberOfChangeEntries * sizeof(ChangeEntry));
429 }
430
431 if (hostPDRHandler && !pdrRecordHandles.empty())
432 {
433 hostPDRHandler->fetchPDR(std::move(pdrRecordHandles));
434 }
435 }
436 else
437 {
438 return PLDM_ERROR_INVALID_DATA;
439 }
440
441 return PLDM_SUCCESS;
442}
443
444int Handler::getPDRRecordHandles(const ChangeEntry* changeEntryData,
445 size_t changeEntryDataSize,
446 size_t numberOfChangeEntries,
447 PDRRecordHandles& pdrRecordHandles)
448{
449 if (numberOfChangeEntries > (changeEntryDataSize / sizeof(ChangeEntry)))
450 {
451 return PLDM_ERROR_INVALID_DATA;
452 }
453 for (size_t i = 0; i < numberOfChangeEntries; i++)
454 {
455 pdrRecordHandles.push_back(changeEntryData[i]);
456 }
457 return PLDM_SUCCESS;
458}
459
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600460} // namespace platform
Deepak Kodihalli557dfb02019-05-12 13:11:17 +0530461} // namespace responder
462} // namespace pldm