blob: c0fff443cf4d9c28141aef6c340a540db7f74a6c [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 Liueccb0c52020-01-14 11:09:56 +08006#include "platform_numeric_effecter.hpp"
George Liu0d7aca82020-03-30 15:01:36 +08007#include "platform_state_effecter.hpp"
George Liu83409572019-12-24 18:42:54 +08008#include "utils.hpp"
9
Deepak Kodihalli557dfb02019-05-12 13:11:17 +053010namespace pldm
11{
Deepak Kodihalli557dfb02019-05-12 13:11:17 +053012namespace responder
13{
Sampa Misraa2fa0702019-05-31 01:28:55 -050014namespace platform
15{
16
Deepak Kodihallic682fe22020-03-04 00:42:54 -060017using InternalFailure =
18 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
19
George Liu1ec85d42020-02-12 16:05:32 +080020static const Json empty{};
21
Zahed Hossain75330f32020-03-24 02:15:03 -050022using EventEntryMap = std::map<EventEntry, DBusInfo>;
23
24const EventEntryMap eventEntryMap = {
25 {
26 0x01010007, // SensorID for VMI Port 0 ipv4 = 7, SensorOffset for the
27 // State Set ID 15 = 1 & PLDM State Set Enumeration List = 1
28 // (Valid Configuration)
29 {"/xyz/openbmc_project/network/vmi/intf0/ipv4/addr0",
30 "xyz.openbmc_project.Object.Enable", "Enabled", "bool", true},
31 },
32 {
33 0x02010007, // SensorID for VMI Port 0 ipv4 = 7, SensorOffset for the
34 // State Set ID 15 = 1 & PLDM State Set Enumeration List = 2
35 // (Invalid Configuration)
36 {"/xyz/openbmc_project/network/vmi/intf0/ipv4/addr0",
37 "xyz.openbmc_project.Object.Enable", "Enabled", "bool", false},
38 },
39 {
40 0x01010008, // SensorID for VMI Port 1 ipv4 = 8, SensorOffset for the
41 // State Set ID 15 = 1 & PLDM State Set Enumeration List = 1
42 // (Valid Configuration)
43 {"/xyz/openbmc_project/network/vmi/intf1/ipv4/addr0",
44 "xyz.openbmc_project.Object.Enable", "Enabled", "bool", true},
45 },
46 {
47 0x02010008, // SensorID for VMI Port 1 ipv4 = 8, SensorOffset for the
48 // State Set ID 15 = 1 & PLDM State Set Enumeration List = 2
49 // (Invalid Configuration)
50 {"/xyz/openbmc_project/network/vmi/intf1/ipv4/addr0",
51 "xyz.openbmc_project.Object.Enable", "Enabled", "bool", false},
52 }};
53
George Liua2870722020-02-11 11:09:30 +080054void Handler::addDbusObjMaps(
55 uint16_t effecterId,
56 std::tuple<pdr_utils::DbusMappings, pdr_utils::DbusValMaps> dbusObj)
George Liu1ec85d42020-02-12 16:05:32 +080057{
58 dbusObjMaps.emplace(effecterId, dbusObj);
59}
60
George Liua2870722020-02-11 11:09:30 +080061const std::tuple<pdr_utils::DbusMappings, pdr_utils::DbusValMaps>&
George Liu1ec85d42020-02-12 16:05:32 +080062 Handler::getDbusObjMaps(uint16_t effecterId) const
63{
64 return dbusObjMaps.at(effecterId);
65}
66
Deepak Kodihallic682fe22020-03-04 00:42:54 -060067void Handler::generate(const std::string& dir, Repo& repo)
68{
69 // A map of PDR type to a lambda that handles creation of that PDR type.
70 // The lambda essentially would parse the platform specific PDR JSONs to
71 // generate the PDR structures. This function iterates through the map to
72 // invoke all lambdas, so that all PDR types can be created.
George Liua2870722020-02-11 11:09:30 +080073
74 const std::map<Type, generatePDR> generateHandlers = {
75 {PLDM_STATE_EFFECTER_PDR,
76 [this](const auto& json, RepoInterface& repo) {
77 pdr_state_effecter::generateStateEffecterPDR<Handler>(json, *this,
78 repo);
George Liu456c9a22020-01-13 11:36:22 +080079 }},
80 {PLDM_NUMERIC_EFFECTER_PDR,
81 [this](const auto& json, RepoInterface& repo) {
82 pdr_numeric_effecter::generateNumericEffecterPDR<Handler>(
83 json, *this, repo);
George Liua2870722020-02-11 11:09:30 +080084 }}};
Deepak Kodihallic682fe22020-03-04 00:42:54 -060085
86 Type pdrType{};
87 for (const auto& dirEntry : fs::directory_iterator(dir))
88 {
89 try
90 {
91 auto json = readJson(dirEntry.path().string());
92 if (!json.empty())
93 {
George Liu1ec85d42020-02-12 16:05:32 +080094 auto effecterPDRs = json.value("effecterPDRs", empty);
95 for (const auto& effecter : effecterPDRs)
96 {
97 pdrType = effecter.value("pdrType", 0);
George Liua2870722020-02-11 11:09:30 +080098 generateHandlers.at(pdrType)(effecter, repo);
George Liu1ec85d42020-02-12 16:05:32 +080099 }
Deepak Kodihallic682fe22020-03-04 00:42:54 -0600100 }
101 }
102 catch (const InternalFailure& e)
103 {
104 std::cerr << "PDR config directory does not exist or empty, TYPE= "
105 << pdrType << "PATH= " << dirEntry
106 << " ERROR=" << e.what() << "\n";
107 }
108 catch (const Json::exception& e)
109 {
110 std::cerr << "Failed parsing PDR JSON file, TYPE= " << pdrType
111 << " ERROR=" << e.what() << "\n";
112 pldm::utils::reportError(
113 "xyz.openbmc_project.bmc.pldm.InternalFailure");
114 }
115 catch (const std::exception& e)
116 {
117 std::cerr << "Failed parsing PDR JSON file, TYPE= " << pdrType
118 << " ERROR=" << e.what() << "\n";
119 pldm::utils::reportError(
120 "xyz.openbmc_project.bmc.pldm.InternalFailure");
121 }
122 }
123}
Deepak Kodihalli557dfb02019-05-12 13:11:17 +0530124
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600125Response Handler::getPDR(const pldm_msg* request, size_t payloadLength)
Deepak Kodihalli557dfb02019-05-12 13:11:17 +0530126{
127 Response response(sizeof(pldm_msg_hdr) + PLDM_GET_PDR_MIN_RESP_BYTES, 0);
128 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
129
130 if (payloadLength != PLDM_GET_PDR_REQ_BYTES)
131 {
George Liufb8611d2019-12-06 10:14:15 +0800132 return CmdHandler::ccOnlyResponse(request, PLDM_ERROR_INVALID_LENGTH);
Deepak Kodihalli557dfb02019-05-12 13:11:17 +0530133 }
134
135 uint32_t recordHandle{};
136 uint32_t dataTransferHandle{};
137 uint8_t transferOpFlag{};
138 uint16_t reqSizeBytes{};
139 uint16_t recordChangeNum{};
140
George Liufb8611d2019-12-06 10:14:15 +0800141 auto rc = decode_get_pdr_req(request, payloadLength, &recordHandle,
142 &dataTransferHandle, &transferOpFlag,
143 &reqSizeBytes, &recordChangeNum);
144 if (rc != PLDM_SUCCESS)
145 {
146 return CmdHandler::ccOnlyResponse(request, rc);
147 }
Deepak Kodihalli557dfb02019-05-12 13:11:17 +0530148
Deepak Kodihalli557dfb02019-05-12 13:11:17 +0530149 uint16_t respSizeBytes{};
150 uint8_t* recordData = nullptr;
151 try
152 {
George Liue53193f2020-02-24 09:23:26 +0800153 pdr_utils::PdrEntry e;
154 auto record = pdr::getRecordByHandle(pdrRepo, recordHandle, e);
155 if (record == NULL)
156 {
157 return CmdHandler::ccOnlyResponse(
158 request, PLDM_PLATFORM_INVALID_RECORD_HANDLE);
159 }
160
Deepak Kodihalli557dfb02019-05-12 13:11:17 +0530161 if (reqSizeBytes)
162 {
George Liue53193f2020-02-24 09:23:26 +0800163 respSizeBytes = e.size;
Deepak Kodihalli557dfb02019-05-12 13:11:17 +0530164 if (respSizeBytes > reqSizeBytes)
165 {
166 respSizeBytes = reqSizeBytes;
167 }
George Liue53193f2020-02-24 09:23:26 +0800168 recordData = e.data;
Deepak Kodihalli557dfb02019-05-12 13:11:17 +0530169 }
170 response.resize(sizeof(pldm_msg_hdr) + PLDM_GET_PDR_MIN_RESP_BYTES +
171 respSizeBytes,
172 0);
173 responsePtr = reinterpret_cast<pldm_msg*>(response.data());
Deepak Kodihalli22b5a7d2020-03-17 23:28:41 -0500174 rc = encode_get_pdr_resp(
175 request->hdr.instance_id, PLDM_SUCCESS, e.handle.nextRecordHandle,
176 0, PLDM_START_AND_END, respSizeBytes, recordData, 0, responsePtr);
George Liufb8611d2019-12-06 10:14:15 +0800177 if (rc != PLDM_SUCCESS)
178 {
179 return ccOnlyResponse(request, rc);
180 }
Deepak Kodihalli557dfb02019-05-12 13:11:17 +0530181 }
Deepak Kodihalli557dfb02019-05-12 13:11:17 +0530182 catch (const std::exception& e)
183 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600184 std::cerr << "Error accessing PDR, HANDLE=" << recordHandle
185 << " ERROR=" << e.what() << "\n";
George Liufb8611d2019-12-06 10:14:15 +0800186 return CmdHandler::ccOnlyResponse(request, PLDM_ERROR);
Deepak Kodihalli557dfb02019-05-12 13:11:17 +0530187 }
188 return response;
189}
190
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600191Response Handler::setStateEffecterStates(const pldm_msg* request,
192 size_t payloadLength)
Sampa Misraa2fa0702019-05-31 01:28:55 -0500193{
194 Response response(
195 sizeof(pldm_msg_hdr) + PLDM_SET_STATE_EFFECTER_STATES_RESP_BYTES, 0);
196 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
197 uint16_t effecterId;
198 uint8_t compEffecterCnt;
199 constexpr auto maxCompositeEffecterCnt = 8;
200 std::vector<set_effecter_state_field> stateField(maxCompositeEffecterCnt,
201 {0, 0});
202
203 if ((payloadLength > PLDM_SET_STATE_EFFECTER_STATES_REQ_BYTES) ||
204 (payloadLength < sizeof(effecterId) + sizeof(compEffecterCnt) +
205 sizeof(set_effecter_state_field)))
206 {
George Liufb8611d2019-12-06 10:14:15 +0800207 return CmdHandler::ccOnlyResponse(request, PLDM_ERROR_INVALID_LENGTH);
Sampa Misraa2fa0702019-05-31 01:28:55 -0500208 }
209
210 int rc = decode_set_state_effecter_states_req(request, payloadLength,
211 &effecterId, &compEffecterCnt,
212 stateField.data());
213
George Liufb8611d2019-12-06 10:14:15 +0800214 if (rc != PLDM_SUCCESS)
Sampa Misraa2fa0702019-05-31 01:28:55 -0500215 {
George Liufb8611d2019-12-06 10:14:15 +0800216 return CmdHandler::ccOnlyResponse(request, rc);
Sampa Misraa2fa0702019-05-31 01:28:55 -0500217 }
218
George Liufb8611d2019-12-06 10:14:15 +0800219 stateField.resize(compEffecterCnt);
220 const pldm::utils::DBusHandler dBusIntf;
George Liu0d7aca82020-03-30 15:01:36 +0800221 rc = platform_state_effecter::setStateEffecterStatesHandler<
222 pldm::utils::DBusHandler, Handler>(dBusIntf, *this, effecterId,
223 stateField);
George Liufb8611d2019-12-06 10:14:15 +0800224 if (rc != PLDM_SUCCESS)
225 {
226 return CmdHandler::ccOnlyResponse(request, rc);
227 }
228
229 rc = encode_set_state_effecter_states_resp(request->hdr.instance_id, rc,
230 responsePtr);
231 if (rc != PLDM_SUCCESS)
232 {
233 return ccOnlyResponse(request, rc);
234 }
235
Sampa Misraa2fa0702019-05-31 01:28:55 -0500236 return response;
237}
238
Tom Joseph56e45c52020-03-16 10:01:45 +0530239Response Handler::platformEventMessage(const pldm_msg* request,
240 size_t payloadLength)
241{
242 uint8_t formatVersion{};
243 uint8_t tid{};
244 uint8_t eventClass{};
245 size_t offset{};
246
247 auto rc = decode_platform_event_message_req(
248 request, payloadLength, &formatVersion, &tid, &eventClass, &offset);
249 if (rc != PLDM_SUCCESS)
250 {
251 return CmdHandler::ccOnlyResponse(request, rc);
252 }
253
254 try
255 {
256 const auto& handlers = eventHandlers.at(eventClass);
257 for (const auto& handler : handlers)
258 {
259 auto rc =
260 handler(request, payloadLength, formatVersion, tid, offset);
261 if (rc != PLDM_SUCCESS)
262 {
263 return CmdHandler::ccOnlyResponse(request, rc);
264 }
265 }
266 }
267 catch (const std::out_of_range& e)
268 {
269 return CmdHandler::ccOnlyResponse(request, PLDM_ERROR_INVALID_DATA);
270 }
271
272 Response response(
273 sizeof(pldm_msg_hdr) + PLDM_PLATFORM_EVENT_MESSAGE_RESP_BYTES, 0);
274 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
275
276 rc = encode_platform_event_message_resp(request->hdr.instance_id, rc,
277 PLDM_EVENT_NO_LOGGING, responsePtr);
278 if (rc != PLDM_SUCCESS)
279 {
280 return ccOnlyResponse(request, rc);
281 }
282
283 return response;
284}
285
286int Handler::sensorEvent(const pldm_msg* request, size_t payloadLength,
287 uint8_t /*formatVersion*/, uint8_t /*tid*/,
288 size_t eventDataOffset)
289{
290 uint16_t sensorId{};
291 uint8_t eventClass{};
292 size_t eventClassDataOffset{};
293 auto eventData =
294 reinterpret_cast<const uint8_t*>(request->payload) + eventDataOffset;
295 auto eventDataSize = payloadLength - eventDataOffset;
296
297 auto rc = decode_sensor_event_data(eventData, eventDataSize, &sensorId,
298 &eventClass, &eventClassDataOffset);
299 if (rc != PLDM_SUCCESS)
300 {
301 return rc;
302 }
303
Zahed Hossain75330f32020-03-24 02:15:03 -0500304 auto eventClassData = reinterpret_cast<const uint8_t*>(request->payload) +
305 eventDataOffset + eventClassDataOffset;
306 auto eventClassDataSize =
307 payloadLength - eventDataOffset - eventClassDataOffset;
308
Tom Joseph56e45c52020-03-16 10:01:45 +0530309 if (eventClass == PLDM_STATE_SENSOR_STATE)
310 {
311 uint8_t sensorOffset{};
312 uint8_t eventState{};
313 uint8_t previousEventState{};
314
Zahed Hossain75330f32020-03-24 02:15:03 -0500315 rc = decode_state_sensor_data(eventClassData, eventClassDataSize,
Tom Joseph56e45c52020-03-16 10:01:45 +0530316 &sensorOffset, &eventState,
317 &previousEventState);
Zahed Hossain75330f32020-03-24 02:15:03 -0500318 if (rc != PLDM_SUCCESS)
319 {
320 return PLDM_ERROR;
321 }
322
323 rc = setSensorEventData(sensorId, sensorOffset, eventState);
324
325 if (rc != PLDM_SUCCESS)
326 {
327 return PLDM_ERROR;
328 }
Tom Joseph56e45c52020-03-16 10:01:45 +0530329 }
330 else
331 {
332 return PLDM_ERROR_INVALID_DATA;
333 }
334
335 return PLDM_SUCCESS;
336}
337
Zahed Hossain75330f32020-03-24 02:15:03 -0500338int Handler::setSensorEventData(uint16_t sensorId, uint8_t sensorOffset,
339 uint8_t eventState)
340{
341 EventEntry eventEntry = ((static_cast<uint32_t>(eventState)) << 24) +
342 ((static_cast<uint32_t>(sensorOffset)) << 16) +
343 sensorId;
344 auto iter = eventEntryMap.find(eventEntry);
345 if (iter == eventEntryMap.end())
346 {
347 return PLDM_SUCCESS;
348 }
349
350 const auto& dBusInfo = iter->second;
351 try
352 {
353 pldm::utils::DBusMapping dbusMapping{
354 dBusInfo.dBusValues.objectPath, dBusInfo.dBusValues.interface,
355 dBusInfo.dBusValues.propertyName, dBusInfo.dBusValues.propertyType};
356 pldm::utils::DBusHandler().setDbusProperty(dbusMapping,
357 dBusInfo.dBusPropertyValue);
358 }
359 catch (std::exception& e)
360 {
361
362 std::cerr
363 << "Error Setting dbus property,SensorID=" << eventEntry
364 << "DBusInfo=" << dBusInfo.dBusValues.objectPath
365 << dBusInfo.dBusValues.interface << dBusInfo.dBusValues.propertyName
366 << "ERROR=" << e.what() << "\n";
367 return PLDM_ERROR;
368 }
369 return PLDM_SUCCESS;
370}
371
Deepak Kodihalli8cb6f662020-04-10 02:55:43 -0500372int Handler::pldmPDRRepositoryChgEvent(const pldm_msg* request,
373 size_t payloadLength,
374 uint8_t /*formatVersion*/,
375 uint8_t /*tid*/, size_t eventDataOffset)
376{
377 uint8_t eventDataFormat{};
378 uint8_t numberOfChangeRecords{};
379 size_t dataOffset{};
380
381 auto eventData =
382 reinterpret_cast<const uint8_t*>(request->payload) + eventDataOffset;
383 auto eventDataSize = payloadLength - eventDataOffset;
384
385 auto rc = decode_pldm_pdr_repository_chg_event_data(
386 eventData, eventDataSize, &eventDataFormat, &numberOfChangeRecords,
387 &dataOffset);
388 if (rc != PLDM_SUCCESS)
389 {
390 return rc;
391 }
392
393 PDRRecordHandles pdrRecordHandles;
394 if (eventDataFormat == FORMAT_IS_PDR_HANDLES)
395 {
396 uint8_t eventDataOperation{};
397 uint8_t numberOfChangeEntries{};
398
399 auto changeRecordData = eventData + dataOffset;
400 auto changeRecordDataSize = eventDataSize - dataOffset;
401
402 while (changeRecordDataSize)
403 {
404 rc = decode_pldm_pdr_repository_change_record_data(
405 changeRecordData, changeRecordDataSize, &eventDataOperation,
406 &numberOfChangeEntries, &dataOffset);
407
408 if (rc != PLDM_SUCCESS)
409 {
410 return rc;
411 }
412
413 if (eventDataOperation == PLDM_RECORDS_ADDED)
414 {
415 rc = getPDRRecordHandles(
416 reinterpret_cast<const ChangeEntry*>(changeRecordData +
417 dataOffset),
418 changeRecordDataSize - dataOffset,
419 static_cast<size_t>(numberOfChangeEntries),
420 pdrRecordHandles);
421
422 if (rc != PLDM_SUCCESS)
423 {
424 return rc;
425 }
426 }
427
428 changeRecordData +=
429 dataOffset + (numberOfChangeEntries * sizeof(ChangeEntry));
430 changeRecordDataSize -=
431 dataOffset + (numberOfChangeEntries * sizeof(ChangeEntry));
432 }
433
434 if (hostPDRHandler && !pdrRecordHandles.empty())
435 {
436 hostPDRHandler->fetchPDR(std::move(pdrRecordHandles));
437 }
438 }
439 else
440 {
441 return PLDM_ERROR_INVALID_DATA;
442 }
443
444 return PLDM_SUCCESS;
445}
446
447int Handler::getPDRRecordHandles(const ChangeEntry* changeEntryData,
448 size_t changeEntryDataSize,
449 size_t numberOfChangeEntries,
450 PDRRecordHandles& pdrRecordHandles)
451{
452 if (numberOfChangeEntries > (changeEntryDataSize / sizeof(ChangeEntry)))
453 {
454 return PLDM_ERROR_INVALID_DATA;
455 }
456 for (size_t i = 0; i < numberOfChangeEntries; i++)
457 {
458 pdrRecordHandles.push_back(changeEntryData[i]);
459 }
460 return PLDM_SUCCESS;
461}
462
George Liueccb0c52020-01-14 11:09:56 +0800463Response Handler::setNumericEffecterValue(const pldm_msg* request,
464 size_t payloadLength)
465{
466 Response response(sizeof(pldm_msg_hdr) +
467 PLDM_SET_NUMERIC_EFFECTER_VALUE_RESP_BYTES);
468 uint16_t effecterId{};
469 uint8_t effecterDataSize{};
470 uint8_t effecterValue[4] = {};
471
472 if ((payloadLength > sizeof(effecterId) + sizeof(effecterDataSize) +
473 sizeof(union_effecter_data_size)) ||
474 (payloadLength < sizeof(effecterId) + sizeof(effecterDataSize) + 1))
475 {
476 return ccOnlyResponse(request, PLDM_ERROR_INVALID_LENGTH);
477 }
478
479 int rc = decode_set_numeric_effecter_value_req(
480 request, payloadLength, &effecterId, &effecterDataSize,
481 reinterpret_cast<uint8_t*>(&effecterValue));
482
483 if (rc == PLDM_SUCCESS)
484 {
485 const pldm::utils::DBusHandler dBusIntf;
486 rc = platform_numeric_effecter::setNumericEffecterValueHandler<
487 pldm::utils::DBusHandler, Handler>(dBusIntf, *this, effecterId,
488 effecterDataSize, effecterValue,
489 sizeof(effecterValue));
490 }
491
492 return ccOnlyResponse(request, rc);
493}
494
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600495} // namespace platform
Deepak Kodihalli557dfb02019-05-12 13:11:17 +0530496} // namespace responder
497} // namespace pldm