blob: c79a2ed4932b7dcd8d08a2acd80d11956959277c [file] [log] [blame]
Deepak Kodihalli557dfb02019-05-12 13:11:17 +05301#pragma once
2
Sampa Misraa2fa0702019-05-31 01:28:55 -05003#include "config.h"
4
George Liu6492f522020-06-16 10:34:05 +08005#include "libpldm/platform.h"
6#include "libpldm/states.h"
7
Deepak Kodihallid130e1a2020-06-17 05:55:32 -05008#include "common/utils.hpp"
TOM JOSEPHd4d97a52020-03-23 14:36:34 +05309#include "event_parser.hpp"
Tom Joseph33e9c7e2020-06-11 22:09:52 +053010#include "fru.hpp"
Deepak Kodihalliac19bd62020-06-16 08:25:23 -050011#include "host-bmc/host_pdr_handler.hpp"
Sampa Misraa2fa0702019-05-31 01:28:55 -050012#include "libpldmresponder/pdr.hpp"
George Liue53193f2020-02-24 09:23:26 +080013#include "libpldmresponder/pdr_utils.hpp"
Deepak Kodihalli1521f6d2020-06-16 08:51:02 -050014#include "pldmd/handler.hpp"
Sampa Misraa2fa0702019-05-31 01:28:55 -050015
Deepak Kodihalli557dfb02019-05-12 13:11:17 +053016#include <stdint.h>
17
Sampa Misraa2fa0702019-05-31 01:28:55 -050018#include <map>
Deepak Kodihalli557dfb02019-05-12 13:11:17 +053019
Deepak Kodihalli557dfb02019-05-12 13:11:17 +053020namespace pldm
21{
Deepak Kodihalli557dfb02019-05-12 13:11:17 +053022namespace responder
23{
Sampa Misraa2fa0702019-05-31 01:28:55 -050024namespace platform
25{
26
George Liu1ec85d42020-02-12 16:05:32 +080027using namespace pldm::utils;
28using namespace pldm::responder::pdr_utils;
29
George Liua2870722020-02-11 11:09:30 +080030using generatePDR =
George Liu36e81352020-07-01 14:40:30 +080031 std::function<void(const pldm::utils::DBusHandler& dBusIntf,
32 const Json& json, pdr_utils::RepoInterface& repo)>;
George Liua2870722020-02-11 11:09:30 +080033
George Liu1ec85d42020-02-12 16:05:32 +080034using EffecterId = uint16_t;
George Liua2870722020-02-11 11:09:30 +080035using DbusObjMaps =
36 std::map<EffecterId,
37 std::tuple<pdr_utils::DbusMappings, pdr_utils::DbusValMaps>>;
Tom Joseph56e45c52020-03-16 10:01:45 +053038using DbusPath = std::string;
39using EffecterObjs = std::vector<DbusPath>;
40using EventType = uint8_t;
41using EventHandler = std::function<int(
42 const pldm_msg* request, size_t payloadLength, uint8_t formatVersion,
43 uint8_t tid, size_t eventDataOffset)>;
44using EventHandlers = std::vector<EventHandler>;
45using EventMap = std::map<EventType, EventHandlers>;
Deepak Kodihallic682fe22020-03-04 00:42:54 -060046
Zahed Hossain75330f32020-03-24 02:15:03 -050047// EventEntry = <uint8_t> - EventState <uint8_t> - SensorOffset <uint16_t> -
48// SensorID
49using EventEntry = uint32_t;
50struct DBusInfo
51{
52 pldm::utils::DBusMapping dBusValues;
53 pldm::utils::PropertyValue dBusPropertyValue;
54};
55
Deepak Kodihallibc669f12019-11-28 08:52:07 -060056class Handler : public CmdHandler
Sampa Misraa2fa0702019-05-31 01:28:55 -050057{
Deepak Kodihallibc669f12019-11-28 08:52:07 -060058 public:
George Liu36e81352020-07-01 14:40:30 +080059 Handler(const pldm::utils::DBusHandler& dBusIntf,
60 const std::string& pdrJsonsDir, const std::string& eventsJsonsDir,
TOM JOSEPHd4d97a52020-03-23 14:36:34 +053061 pldm_pdr* repo, HostPDRHandler* hostPDRHandler,
Tom Joseph33e9c7e2020-06-11 22:09:52 +053062 fru::Handler* fruHandler,
Tom Joseph56e45c52020-03-16 10:01:45 +053063 const std::optional<EventMap>& addOnHandlersMap = std::nullopt) :
Pavithra Barithaya51efaf82020-04-02 02:42:27 -050064 pdrRepo(repo),
Tom Joseph33e9c7e2020-06-11 22:09:52 +053065 hostPDRHandler(hostPDRHandler), stateSensorHandler(eventsJsonsDir),
66 fruHandler(fruHandler)
Sampa Misraa2fa0702019-05-31 01:28:55 -050067 {
George Liu36e81352020-07-01 14:40:30 +080068 generate(dBusIntf, pdrJsonsDir, pdrRepo);
Deepak Kodihallic682fe22020-03-04 00:42:54 -060069
Deepak Kodihallibc669f12019-11-28 08:52:07 -060070 handlers.emplace(PLDM_GET_PDR,
71 [this](const pldm_msg* request, size_t payloadLength) {
72 return this->getPDR(request, payloadLength);
73 });
George Liueccb0c52020-01-14 11:09:56 +080074 handlers.emplace(PLDM_SET_NUMERIC_EFFECTER_VALUE,
75 [this](const pldm_msg* request, size_t payloadLength) {
76 return this->setNumericEffecterValue(
77 request, payloadLength);
78 });
Deepak Kodihallibc669f12019-11-28 08:52:07 -060079 handlers.emplace(PLDM_SET_STATE_EFFECTER_STATES,
80 [this](const pldm_msg* request, size_t payloadLength) {
81 return this->setStateEffecterStates(request,
82 payloadLength);
83 });
Tom Joseph56e45c52020-03-16 10:01:45 +053084 handlers.emplace(PLDM_PLATFORM_EVENT_MESSAGE,
85 [this](const pldm_msg* request, size_t payloadLength) {
86 return this->platformEventMessage(request,
87 payloadLength);
88 });
89
90 // Default handler for PLDM Events
91 eventHandlers[PLDM_SENSOR_EVENT].emplace_back(
92 [this](const pldm_msg* request, size_t payloadLength,
93 uint8_t formatVersion, uint8_t tid, size_t eventDataOffset) {
94 return this->sensorEvent(request, payloadLength, formatVersion,
95 tid, eventDataOffset);
96 });
Deepak Kodihalli8cb6f662020-04-10 02:55:43 -050097 eventHandlers[PLDM_PDR_REPOSITORY_CHG_EVENT].emplace_back(
98 [this](const pldm_msg* request, size_t payloadLength,
99 uint8_t formatVersion, uint8_t tid, size_t eventDataOffset) {
100 return this->pldmPDRRepositoryChgEvent(request, payloadLength,
101 formatVersion, tid,
102 eventDataOffset);
103 });
Tom Joseph56e45c52020-03-16 10:01:45 +0530104
105 // Additional OEM event handlers for PLDM events, append it to the
106 // standard handlers
107 if (addOnHandlersMap)
108 {
109 auto addOnHandlers = addOnHandlersMap.value();
110 for (EventMap::iterator iter = addOnHandlers.begin();
111 iter != addOnHandlers.end(); ++iter)
112 {
113 auto search = eventHandlers.find(iter->first);
114 if (search != eventHandlers.end())
115 {
116 search->second.insert(std::end(search->second),
117 std::begin(iter->second),
118 std::end(iter->second));
119 }
120 else
121 {
122 eventHandlers.emplace(iter->first, iter->second);
123 }
124 }
125 }
Sampa Misraa2fa0702019-05-31 01:28:55 -0500126 }
127
George Liu1ec85d42020-02-12 16:05:32 +0800128 pdr_utils::Repo& getRepo()
Deepak Kodihallic682fe22020-03-04 00:42:54 -0600129 {
George Liu1ec85d42020-02-12 16:05:32 +0800130 return this->pdrRepo;
Deepak Kodihallic682fe22020-03-04 00:42:54 -0600131 }
132
George Liu1ec85d42020-02-12 16:05:32 +0800133 /** @brief Add D-Bus mapping and value mapping(stateId to D-Bus) for the
134 * effecterId. If the same id is added, the previous dbusObjs will
135 * be "over-written".
136 *
137 * @param[in] effecterId - effecter id
138 * @param[in] dbusObj - list of D-Bus object structure and list of D-Bus
139 * property value to attribute value
140 */
George Liua2870722020-02-11 11:09:30 +0800141 void addDbusObjMaps(
142 uint16_t effecterId,
143 std::tuple<pdr_utils::DbusMappings, pdr_utils::DbusValMaps> dbusObj);
George Liu1ec85d42020-02-12 16:05:32 +0800144
145 /** @brief Retrieve an effecter id -> D-Bus objects mapping
146 *
147 * @param[in] effecterId - effecter id
148 *
George Liua2870722020-02-11 11:09:30 +0800149 * @return std::tuple<pdr_utils::DbusMappings, pdr_utils::DbusValMaps> -
150 * list of D-Bus object structure and list of D-Bus property value
151 * to attribute value
George Liu1ec85d42020-02-12 16:05:32 +0800152 */
George Liua2870722020-02-11 11:09:30 +0800153 const std::tuple<pdr_utils::DbusMappings, pdr_utils::DbusValMaps>&
George Liu1ec85d42020-02-12 16:05:32 +0800154 getDbusObjMaps(uint16_t effecterId) const;
Deepak Kodihallic682fe22020-03-04 00:42:54 -0600155
156 uint16_t getNextEffecterId()
157 {
158 return ++nextEffecterId;
159 }
160
161 /** @brief Parse PDR JSONs and build PDR repository
162 *
George Liu36e81352020-07-01 14:40:30 +0800163 * @param[in] dBusIntf - The interface object
Deepak Kodihallic682fe22020-03-04 00:42:54 -0600164 * @param[in] dir - directory housing platform specific PDR JSON files
165 * @param[in] repo - instance of concrete implementation of Repo
166 */
George Liu36e81352020-07-01 14:40:30 +0800167 void generate(const pldm::utils::DBusHandler& dBusIntf,
168 const std::string& dir, Repo& repo);
Deepak Kodihallic682fe22020-03-04 00:42:54 -0600169
170 /** @brief Parse PDR JSONs and build state effecter PDR repository
171 *
172 * @param[in] json - platform specific PDR JSON files
173 * @param[in] repo - instance of state effecter implementation of Repo
174 */
175 void generateStateEffecterRepo(const Json& json, Repo& repo);
176
Tom Joseph56e45c52020-03-16 10:01:45 +0530177 /** @brief map of PLDM event type to EventHandlers
178 *
179 */
180 EventMap eventHandlers;
181
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600182 /** @brief Handler for GetPDR
183 *
184 * @param[in] request - Request message payload
185 * @param[in] payloadLength - Request payload length
186 * @param[out] Response - Response message written here
187 */
188 Response getPDR(const pldm_msg* request, size_t payloadLength);
Sampa Misraa2fa0702019-05-31 01:28:55 -0500189
George Liueccb0c52020-01-14 11:09:56 +0800190 /** @brief Handler for setNumericEffecterValue
191 *
192 * @param[in] request - Request message
193 * @param[in] payloadLength - Request payload length
194 * @return Response - PLDM Response message
195 */
196 Response setNumericEffecterValue(const pldm_msg* request,
197 size_t payloadLength);
198
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600199 /** @brief Handler for setStateEffecterStates
200 *
201 * @param[in] request - Request message
202 * @param[in] payloadLength - Request payload length
203 * @return Response - PLDM Response message
204 */
205 Response setStateEffecterStates(const pldm_msg* request,
206 size_t payloadLength);
207
Tom Joseph56e45c52020-03-16 10:01:45 +0530208 /** @brief Handler for PlatformEventMessage
209 *
210 * @param[in] request - Request message
211 * @param[in] payloadLength - Request payload length
212 * @return Response - PLDM Response message
213 */
214 Response platformEventMessage(const pldm_msg* request,
215 size_t payloadLength);
216
217 /** @brief Handler for event class Sensor event
218 *
219 * @param[in] request - Request message
220 * @param[in] payloadLength - Request payload length
221 * @param[in] formatVersion - Version of the event format
222 * @param[in] tid - Terminus ID of the event's originator
223 * @param[in] eventDataOffset - Offset of the event data in the request
224 * message
225 * @return PLDM completion code
226 */
227 int sensorEvent(const pldm_msg* request, size_t payloadLength,
228 uint8_t formatVersion, uint8_t tid, size_t eventDataOffset);
229
Deepak Kodihalli8cb6f662020-04-10 02:55:43 -0500230 /** @brief Handler for pldmPDRRepositoryChgEvent
231 *
232 * @param[in] request - Request message
233 * @param[in] payloadLength - Request payload length
234 * @param[in] formatVersion - Version of the event format
235 * @param[in] tid - Terminus ID of the event's originator
236 * @param[in] eventDataOffset - Offset of the event data in the request
237 * message
238 * @return PLDM completion code
239 */
240 int pldmPDRRepositoryChgEvent(const pldm_msg* request, size_t payloadLength,
241 uint8_t formatVersion, uint8_t tid,
242 size_t eventDataOffset);
243
244 /** @brief Handler for extracting the PDR handles from changeEntries
245 *
246 * @param[in] changeEntryData - ChangeEntry data from changeRecord
247 * @param[in] changeEntryDataSize - total size of changeEntryData
248 * @param[in] numberOfChangeEntries - total number of changeEntries to
249 * extract
250 * @param[out] pdrRecordHandles - std::vector where the extracted PDR
251 * handles are placed
252 * @return PLDM completion code
253 */
254 int getPDRRecordHandles(const ChangeEntry* changeEntryData,
255 size_t changeEntryDataSize,
256 size_t numberOfChangeEntries,
257 PDRRecordHandles& pdrRecordHandles);
258
Zahed Hossain75330f32020-03-24 02:15:03 -0500259 /** @brief Handler for setting Sensor event data
260 *
261 * @param[in] sensorId - sensorID value of the sensor
262 * @param[in] sensorOffset - Identifies which state sensor within a
263 * composite state sensor the event is being returned for
264 * @param[in] eventState - The event state value from the state change that
265 * triggered the event message
266 * @return PLDM completion code
267 */
268 int setSensorEventData(uint16_t sensorId, uint8_t sensorOffset,
269 uint8_t eventState);
270
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600271 /** @brief Function to set the effecter requested by pldm requester
272 * @param[in] dBusIntf - The interface object
273 * @param[in] effecterId - Effecter ID sent by the requester to act on
274 * @param[in] stateField - The state field data for each of the states,
275 * equal to composite effecter count in number
276 * @return - Success or failure in setting the states. Returns failure in
277 * terms of PLDM completion codes if atleast one state fails to be set
278 */
279 template <class DBusInterface>
280 int setStateEffecterStatesHandler(
Deepak Kodihallic682fe22020-03-04 00:42:54 -0600281 const DBusInterface& dBusIntf, uint16_t effecterId,
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600282 const std::vector<set_effecter_state_field>& stateField)
Sampa Misraa2fa0702019-05-31 01:28:55 -0500283 {
George Liue53193f2020-02-24 09:23:26 +0800284 using namespace pldm::responder::pdr;
George Liu1e44c732020-02-28 20:20:06 +0800285 using namespace pldm::utils;
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600286 using StateSetNum = uint8_t;
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600287
288 state_effecter_possible_states* states = nullptr;
289 pldm_state_effecter_pdr* pdr = nullptr;
290 uint8_t compEffecterCnt = stateField.size();
George Liu1ec85d42020-02-12 16:05:32 +0800291
292 std::unique_ptr<pldm_pdr, decltype(&pldm_pdr_destroy)>
293 stateEffecterPdrRepo(pldm_pdr_init(), pldm_pdr_destroy);
294 Repo stateEffecterPDRs(stateEffecterPdrRepo.get());
295 getRepoByType(pdrRepo, stateEffecterPDRs, PLDM_STATE_EFFECTER_PDR);
296 if (stateEffecterPDRs.empty())
297 {
298 std::cerr << "Failed to get record by PDR type\n";
299 return PLDM_PLATFORM_INVALID_EFFECTER_ID;
300 }
301
George Liue53193f2020-02-24 09:23:26 +0800302 PdrEntry pdrEntry{};
George Liu1ec85d42020-02-12 16:05:32 +0800303 auto pdrRecord = stateEffecterPDRs.getFirstRecord(pdrEntry);
George Liue53193f2020-02-24 09:23:26 +0800304 while (pdrRecord)
305 {
306 pdr = reinterpret_cast<pldm_state_effecter_pdr*>(pdrEntry.data);
307 if (pdr->effecter_id != effecterId)
Sampa Misraa2fa0702019-05-31 01:28:55 -0500308 {
George Liue53193f2020-02-24 09:23:26 +0800309 pdr = nullptr;
George Liu1ec85d42020-02-12 16:05:32 +0800310 pdrRecord =
311 stateEffecterPDRs.getNextRecord(pdrRecord, pdrEntry);
George Liue53193f2020-02-24 09:23:26 +0800312 continue;
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600313 }
George Liue53193f2020-02-24 09:23:26 +0800314
315 states = reinterpret_cast<state_effecter_possible_states*>(
316 pdr->possible_states);
317 if (compEffecterCnt > pdr->composite_effecter_count)
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600318 {
George Liue53193f2020-02-24 09:23:26 +0800319 std::cerr << "The requester sent wrong composite effecter"
320 << " count for the effecter, EFFECTER_ID="
321 << effecterId << "COMP_EFF_CNT=" << compEffecterCnt
322 << "\n";
323 return PLDM_ERROR_INVALID_DATA;
Sampa Misraa2fa0702019-05-31 01:28:55 -0500324 }
George Liue53193f2020-02-24 09:23:26 +0800325 break;
326 }
327
328 if (!pdr)
329 {
330 return PLDM_PLATFORM_INVALID_EFFECTER_ID;
Sampa Misraa2fa0702019-05-31 01:28:55 -0500331 }
Sampa Misraa2fa0702019-05-31 01:28:55 -0500332
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600333 int rc = PLDM_SUCCESS;
George Liu1ec85d42020-02-12 16:05:32 +0800334 try
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600335 {
George Liu1ec85d42020-02-12 16:05:32 +0800336 const auto& [dbusMappings, dbusValMaps] =
337 dbusObjMaps.at(effecterId);
338 for (uint8_t currState = 0; currState < compEffecterCnt;
339 ++currState)
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600340 {
George Liu1ec85d42020-02-12 16:05:32 +0800341 std::vector<StateSetNum> allowed{};
342 // computation is based on table 79 from DSP0248 v1.1.1
343 uint8_t bitfieldIndex =
344 stateField[currState].effecter_state / 8;
345 uint8_t bit =
346 stateField[currState].effecter_state - (8 * bitfieldIndex);
347 if (states->possible_states_size < bitfieldIndex ||
348 !(states->states[bitfieldIndex].byte & (1 << bit)))
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600349 {
George Liu1ec85d42020-02-12 16:05:32 +0800350 std::cerr
351 << "Invalid state set value, EFFECTER_ID=" << effecterId
352 << " VALUE=" << stateField[currState].effecter_state
353 << " COMPOSITE_EFFECTER_ID=" << currState
354 << " DBUS_PATH=" << dbusMappings[currState].objectPath
355 << "\n";
356 rc = PLDM_PLATFORM_SET_EFFECTER_UNSUPPORTED_SENSORSTATE;
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600357 break;
358 }
George Liu1ec85d42020-02-12 16:05:32 +0800359 const DBusMapping& dbusMapping = dbusMappings[currState];
360 const StatestoDbusVal& dbusValToMap = dbusValMaps[currState];
361
362 if (stateField[currState].set_request == PLDM_REQUEST_SET)
363 {
364 try
365 {
366 dBusIntf.setDbusProperty(
367 dbusMapping,
368 dbusValToMap.at(
369 stateField[currState].effecter_state));
370 }
371 catch (const std::exception& e)
372 {
373 std::cerr
374 << "Error setting property, ERROR=" << e.what()
375 << " PROPERTY=" << dbusMapping.propertyName
376 << " INTERFACE="
377 << dbusMapping.interface << " PATH="
378 << dbusMapping.objectPath << "\n";
379 return PLDM_ERROR;
380 }
381 }
382 uint8_t* nextState =
383 reinterpret_cast<uint8_t*>(states) +
384 sizeof(state_effecter_possible_states) -
385 sizeof(states->states) +
386 (states->possible_states_size * sizeof(states->states));
387 states = reinterpret_cast<state_effecter_possible_states*>(
388 nextState);
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600389 }
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600390 }
George Liu1ec85d42020-02-12 16:05:32 +0800391 catch (const std::out_of_range& e)
392 {
393 std::cerr << "the effecterId does not exist. effecter id: "
394 << effecterId << e.what() << '\n';
395 }
396
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600397 return rc;
398 }
Deepak Kodihallic682fe22020-03-04 00:42:54 -0600399
400 private:
401 pdr_utils::Repo pdrRepo;
402 uint16_t nextEffecterId{};
George Liu1ec85d42020-02-12 16:05:32 +0800403 DbusObjMaps dbusObjMaps{};
Pavithra Barithaya51efaf82020-04-02 02:42:27 -0500404 HostPDRHandler* hostPDRHandler;
TOM JOSEPHd4d97a52020-03-23 14:36:34 +0530405 events::StateSensorHandler stateSensorHandler;
Tom Joseph33e9c7e2020-06-11 22:09:52 +0530406 fru::Handler* fruHandler;
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600407};
408
409} // namespace platform
Deepak Kodihalli557dfb02019-05-12 13:11:17 +0530410} // namespace responder
411} // namespace pldm