blob: ccd3ddfc37057e28fcf6317c766f41e124c6eba7 [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
TOM JOSEPHd4d97a52020-03-23 14:36:34 +05308#include "event_parser.hpp"
Deepak Kodihallibc669f12019-11-28 08:52:07 -06009#include "handler.hpp"
Deepak Kodihalliac19bd62020-06-16 08:25:23 -050010#include "host-bmc/host_pdr_handler.hpp"
Sampa Misraa2fa0702019-05-31 01:28:55 -050011#include "libpldmresponder/pdr.hpp"
George Liue53193f2020-02-24 09:23:26 +080012#include "libpldmresponder/pdr_utils.hpp"
George Liu83409572019-12-24 18:42:54 +080013#include "utils.hpp"
Sampa Misraa2fa0702019-05-31 01:28:55 -050014
Deepak Kodihalli557dfb02019-05-12 13:11:17 +053015#include <stdint.h>
16
Sampa Misraa2fa0702019-05-31 01:28:55 -050017#include <map>
Deepak Kodihalli557dfb02019-05-12 13:11:17 +053018
Deepak Kodihalli557dfb02019-05-12 13:11:17 +053019namespace pldm
20{
Deepak Kodihalli557dfb02019-05-12 13:11:17 +053021namespace responder
22{
Sampa Misraa2fa0702019-05-31 01:28:55 -050023namespace platform
24{
25
George Liu1ec85d42020-02-12 16:05:32 +080026using namespace pldm::utils;
27using namespace pldm::responder::pdr_utils;
28
George Liua2870722020-02-11 11:09:30 +080029using generatePDR =
30 std::function<void(const Json& json, pdr_utils::RepoInterface& repo)>;
31
George Liu1ec85d42020-02-12 16:05:32 +080032using EffecterId = uint16_t;
George Liua2870722020-02-11 11:09:30 +080033using DbusObjMaps =
34 std::map<EffecterId,
35 std::tuple<pdr_utils::DbusMappings, pdr_utils::DbusValMaps>>;
Tom Joseph56e45c52020-03-16 10:01:45 +053036using DbusPath = std::string;
37using EffecterObjs = std::vector<DbusPath>;
38using EventType = uint8_t;
39using EventHandler = std::function<int(
40 const pldm_msg* request, size_t payloadLength, uint8_t formatVersion,
41 uint8_t tid, size_t eventDataOffset)>;
42using EventHandlers = std::vector<EventHandler>;
43using EventMap = std::map<EventType, EventHandlers>;
Deepak Kodihallic682fe22020-03-04 00:42:54 -060044
Zahed Hossain75330f32020-03-24 02:15:03 -050045// EventEntry = <uint8_t> - EventState <uint8_t> - SensorOffset <uint16_t> -
46// SensorID
47using EventEntry = uint32_t;
48struct DBusInfo
49{
50 pldm::utils::DBusMapping dBusValues;
51 pldm::utils::PropertyValue dBusPropertyValue;
52};
53
Deepak Kodihallibc669f12019-11-28 08:52:07 -060054class Handler : public CmdHandler
Sampa Misraa2fa0702019-05-31 01:28:55 -050055{
Deepak Kodihallibc669f12019-11-28 08:52:07 -060056 public:
TOM JOSEPHd4d97a52020-03-23 14:36:34 +053057 Handler(const std::string& pdrJsonsDir, const std::string& eventsJsonsDir,
58 pldm_pdr* repo, HostPDRHandler* hostPDRHandler,
Tom Joseph56e45c52020-03-16 10:01:45 +053059 const std::optional<EventMap>& addOnHandlersMap = std::nullopt) :
Pavithra Barithaya51efaf82020-04-02 02:42:27 -050060 pdrRepo(repo),
TOM JOSEPHd4d97a52020-03-23 14:36:34 +053061 hostPDRHandler(hostPDRHandler), stateSensorHandler(eventsJsonsDir)
Sampa Misraa2fa0702019-05-31 01:28:55 -050062 {
TOM JOSEPHd4d97a52020-03-23 14:36:34 +053063 generate(pdrJsonsDir, pdrRepo);
Deepak Kodihallic682fe22020-03-04 00:42:54 -060064
Deepak Kodihallibc669f12019-11-28 08:52:07 -060065 handlers.emplace(PLDM_GET_PDR,
66 [this](const pldm_msg* request, size_t payloadLength) {
67 return this->getPDR(request, payloadLength);
68 });
George Liueccb0c52020-01-14 11:09:56 +080069 handlers.emplace(PLDM_SET_NUMERIC_EFFECTER_VALUE,
70 [this](const pldm_msg* request, size_t payloadLength) {
71 return this->setNumericEffecterValue(
72 request, payloadLength);
73 });
Deepak Kodihallibc669f12019-11-28 08:52:07 -060074 handlers.emplace(PLDM_SET_STATE_EFFECTER_STATES,
75 [this](const pldm_msg* request, size_t payloadLength) {
76 return this->setStateEffecterStates(request,
77 payloadLength);
78 });
Tom Joseph56e45c52020-03-16 10:01:45 +053079 handlers.emplace(PLDM_PLATFORM_EVENT_MESSAGE,
80 [this](const pldm_msg* request, size_t payloadLength) {
81 return this->platformEventMessage(request,
82 payloadLength);
83 });
84
85 // Default handler for PLDM Events
86 eventHandlers[PLDM_SENSOR_EVENT].emplace_back(
87 [this](const pldm_msg* request, size_t payloadLength,
88 uint8_t formatVersion, uint8_t tid, size_t eventDataOffset) {
89 return this->sensorEvent(request, payloadLength, formatVersion,
90 tid, eventDataOffset);
91 });
Deepak Kodihalli8cb6f662020-04-10 02:55:43 -050092 eventHandlers[PLDM_PDR_REPOSITORY_CHG_EVENT].emplace_back(
93 [this](const pldm_msg* request, size_t payloadLength,
94 uint8_t formatVersion, uint8_t tid, size_t eventDataOffset) {
95 return this->pldmPDRRepositoryChgEvent(request, payloadLength,
96 formatVersion, tid,
97 eventDataOffset);
98 });
Tom Joseph56e45c52020-03-16 10:01:45 +053099
100 // Additional OEM event handlers for PLDM events, append it to the
101 // standard handlers
102 if (addOnHandlersMap)
103 {
104 auto addOnHandlers = addOnHandlersMap.value();
105 for (EventMap::iterator iter = addOnHandlers.begin();
106 iter != addOnHandlers.end(); ++iter)
107 {
108 auto search = eventHandlers.find(iter->first);
109 if (search != eventHandlers.end())
110 {
111 search->second.insert(std::end(search->second),
112 std::begin(iter->second),
113 std::end(iter->second));
114 }
115 else
116 {
117 eventHandlers.emplace(iter->first, iter->second);
118 }
119 }
120 }
Sampa Misraa2fa0702019-05-31 01:28:55 -0500121 }
122
George Liu1ec85d42020-02-12 16:05:32 +0800123 pdr_utils::Repo& getRepo()
Deepak Kodihallic682fe22020-03-04 00:42:54 -0600124 {
George Liu1ec85d42020-02-12 16:05:32 +0800125 return this->pdrRepo;
Deepak Kodihallic682fe22020-03-04 00:42:54 -0600126 }
127
George Liu1ec85d42020-02-12 16:05:32 +0800128 /** @brief Add D-Bus mapping and value mapping(stateId to D-Bus) for the
129 * effecterId. If the same id is added, the previous dbusObjs will
130 * be "over-written".
131 *
132 * @param[in] effecterId - effecter id
133 * @param[in] dbusObj - list of D-Bus object structure and list of D-Bus
134 * property value to attribute value
135 */
George Liua2870722020-02-11 11:09:30 +0800136 void addDbusObjMaps(
137 uint16_t effecterId,
138 std::tuple<pdr_utils::DbusMappings, pdr_utils::DbusValMaps> dbusObj);
George Liu1ec85d42020-02-12 16:05:32 +0800139
140 /** @brief Retrieve an effecter id -> D-Bus objects mapping
141 *
142 * @param[in] effecterId - effecter id
143 *
George Liua2870722020-02-11 11:09:30 +0800144 * @return std::tuple<pdr_utils::DbusMappings, pdr_utils::DbusValMaps> -
145 * list of D-Bus object structure and list of D-Bus property value
146 * to attribute value
George Liu1ec85d42020-02-12 16:05:32 +0800147 */
George Liua2870722020-02-11 11:09:30 +0800148 const std::tuple<pdr_utils::DbusMappings, pdr_utils::DbusValMaps>&
George Liu1ec85d42020-02-12 16:05:32 +0800149 getDbusObjMaps(uint16_t effecterId) const;
Deepak Kodihallic682fe22020-03-04 00:42:54 -0600150
151 uint16_t getNextEffecterId()
152 {
153 return ++nextEffecterId;
154 }
155
156 /** @brief Parse PDR JSONs and build PDR repository
157 *
158 * @param[in] dir - directory housing platform specific PDR JSON files
159 * @param[in] repo - instance of concrete implementation of Repo
160 */
161 void generate(const std::string& dir, Repo& repo);
162
163 /** @brief Parse PDR JSONs and build state effecter PDR repository
164 *
165 * @param[in] json - platform specific PDR JSON files
166 * @param[in] repo - instance of state effecter implementation of Repo
167 */
168 void generateStateEffecterRepo(const Json& json, Repo& repo);
169
Tom Joseph56e45c52020-03-16 10:01:45 +0530170 /** @brief map of PLDM event type to EventHandlers
171 *
172 */
173 EventMap eventHandlers;
174
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600175 /** @brief Handler for GetPDR
176 *
177 * @param[in] request - Request message payload
178 * @param[in] payloadLength - Request payload length
179 * @param[out] Response - Response message written here
180 */
181 Response getPDR(const pldm_msg* request, size_t payloadLength);
Sampa Misraa2fa0702019-05-31 01:28:55 -0500182
George Liueccb0c52020-01-14 11:09:56 +0800183 /** @brief Handler for setNumericEffecterValue
184 *
185 * @param[in] request - Request message
186 * @param[in] payloadLength - Request payload length
187 * @return Response - PLDM Response message
188 */
189 Response setNumericEffecterValue(const pldm_msg* request,
190 size_t payloadLength);
191
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600192 /** @brief Handler for setStateEffecterStates
193 *
194 * @param[in] request - Request message
195 * @param[in] payloadLength - Request payload length
196 * @return Response - PLDM Response message
197 */
198 Response setStateEffecterStates(const pldm_msg* request,
199 size_t payloadLength);
200
Tom Joseph56e45c52020-03-16 10:01:45 +0530201 /** @brief Handler for PlatformEventMessage
202 *
203 * @param[in] request - Request message
204 * @param[in] payloadLength - Request payload length
205 * @return Response - PLDM Response message
206 */
207 Response platformEventMessage(const pldm_msg* request,
208 size_t payloadLength);
209
210 /** @brief Handler for event class Sensor event
211 *
212 * @param[in] request - Request message
213 * @param[in] payloadLength - Request payload length
214 * @param[in] formatVersion - Version of the event format
215 * @param[in] tid - Terminus ID of the event's originator
216 * @param[in] eventDataOffset - Offset of the event data in the request
217 * message
218 * @return PLDM completion code
219 */
220 int sensorEvent(const pldm_msg* request, size_t payloadLength,
221 uint8_t formatVersion, uint8_t tid, size_t eventDataOffset);
222
Deepak Kodihalli8cb6f662020-04-10 02:55:43 -0500223 /** @brief Handler for pldmPDRRepositoryChgEvent
224 *
225 * @param[in] request - Request message
226 * @param[in] payloadLength - Request payload length
227 * @param[in] formatVersion - Version of the event format
228 * @param[in] tid - Terminus ID of the event's originator
229 * @param[in] eventDataOffset - Offset of the event data in the request
230 * message
231 * @return PLDM completion code
232 */
233 int pldmPDRRepositoryChgEvent(const pldm_msg* request, size_t payloadLength,
234 uint8_t formatVersion, uint8_t tid,
235 size_t eventDataOffset);
236
237 /** @brief Handler for extracting the PDR handles from changeEntries
238 *
239 * @param[in] changeEntryData - ChangeEntry data from changeRecord
240 * @param[in] changeEntryDataSize - total size of changeEntryData
241 * @param[in] numberOfChangeEntries - total number of changeEntries to
242 * extract
243 * @param[out] pdrRecordHandles - std::vector where the extracted PDR
244 * handles are placed
245 * @return PLDM completion code
246 */
247 int getPDRRecordHandles(const ChangeEntry* changeEntryData,
248 size_t changeEntryDataSize,
249 size_t numberOfChangeEntries,
250 PDRRecordHandles& pdrRecordHandles);
251
Zahed Hossain75330f32020-03-24 02:15:03 -0500252 /** @brief Handler for setting Sensor event data
253 *
254 * @param[in] sensorId - sensorID value of the sensor
255 * @param[in] sensorOffset - Identifies which state sensor within a
256 * composite state sensor the event is being returned for
257 * @param[in] eventState - The event state value from the state change that
258 * triggered the event message
259 * @return PLDM completion code
260 */
261 int setSensorEventData(uint16_t sensorId, uint8_t sensorOffset,
262 uint8_t eventState);
263
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600264 /** @brief Function to set the effecter requested by pldm requester
265 * @param[in] dBusIntf - The interface object
266 * @param[in] effecterId - Effecter ID sent by the requester to act on
267 * @param[in] stateField - The state field data for each of the states,
268 * equal to composite effecter count in number
269 * @return - Success or failure in setting the states. Returns failure in
270 * terms of PLDM completion codes if atleast one state fails to be set
271 */
272 template <class DBusInterface>
273 int setStateEffecterStatesHandler(
Deepak Kodihallic682fe22020-03-04 00:42:54 -0600274 const DBusInterface& dBusIntf, uint16_t effecterId,
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600275 const std::vector<set_effecter_state_field>& stateField)
Sampa Misraa2fa0702019-05-31 01:28:55 -0500276 {
George Liue53193f2020-02-24 09:23:26 +0800277 using namespace pldm::responder::pdr;
George Liu1e44c732020-02-28 20:20:06 +0800278 using namespace pldm::utils;
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600279 using StateSetNum = uint8_t;
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600280
281 state_effecter_possible_states* states = nullptr;
282 pldm_state_effecter_pdr* pdr = nullptr;
283 uint8_t compEffecterCnt = stateField.size();
George Liu1ec85d42020-02-12 16:05:32 +0800284
285 std::unique_ptr<pldm_pdr, decltype(&pldm_pdr_destroy)>
286 stateEffecterPdrRepo(pldm_pdr_init(), pldm_pdr_destroy);
287 Repo stateEffecterPDRs(stateEffecterPdrRepo.get());
288 getRepoByType(pdrRepo, stateEffecterPDRs, PLDM_STATE_EFFECTER_PDR);
289 if (stateEffecterPDRs.empty())
290 {
291 std::cerr << "Failed to get record by PDR type\n";
292 return PLDM_PLATFORM_INVALID_EFFECTER_ID;
293 }
294
George Liue53193f2020-02-24 09:23:26 +0800295 PdrEntry pdrEntry{};
George Liu1ec85d42020-02-12 16:05:32 +0800296 auto pdrRecord = stateEffecterPDRs.getFirstRecord(pdrEntry);
George Liue53193f2020-02-24 09:23:26 +0800297 while (pdrRecord)
298 {
299 pdr = reinterpret_cast<pldm_state_effecter_pdr*>(pdrEntry.data);
300 if (pdr->effecter_id != effecterId)
Sampa Misraa2fa0702019-05-31 01:28:55 -0500301 {
George Liue53193f2020-02-24 09:23:26 +0800302 pdr = nullptr;
George Liu1ec85d42020-02-12 16:05:32 +0800303 pdrRecord =
304 stateEffecterPDRs.getNextRecord(pdrRecord, pdrEntry);
George Liue53193f2020-02-24 09:23:26 +0800305 continue;
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600306 }
George Liue53193f2020-02-24 09:23:26 +0800307
308 states = reinterpret_cast<state_effecter_possible_states*>(
309 pdr->possible_states);
310 if (compEffecterCnt > pdr->composite_effecter_count)
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600311 {
George Liue53193f2020-02-24 09:23:26 +0800312 std::cerr << "The requester sent wrong composite effecter"
313 << " count for the effecter, EFFECTER_ID="
314 << effecterId << "COMP_EFF_CNT=" << compEffecterCnt
315 << "\n";
316 return PLDM_ERROR_INVALID_DATA;
Sampa Misraa2fa0702019-05-31 01:28:55 -0500317 }
George Liue53193f2020-02-24 09:23:26 +0800318 break;
319 }
320
321 if (!pdr)
322 {
323 return PLDM_PLATFORM_INVALID_EFFECTER_ID;
Sampa Misraa2fa0702019-05-31 01:28:55 -0500324 }
Sampa Misraa2fa0702019-05-31 01:28:55 -0500325
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600326 int rc = PLDM_SUCCESS;
George Liu1ec85d42020-02-12 16:05:32 +0800327 try
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600328 {
George Liu1ec85d42020-02-12 16:05:32 +0800329 const auto& [dbusMappings, dbusValMaps] =
330 dbusObjMaps.at(effecterId);
331 for (uint8_t currState = 0; currState < compEffecterCnt;
332 ++currState)
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600333 {
George Liu1ec85d42020-02-12 16:05:32 +0800334 std::vector<StateSetNum> allowed{};
335 // computation is based on table 79 from DSP0248 v1.1.1
336 uint8_t bitfieldIndex =
337 stateField[currState].effecter_state / 8;
338 uint8_t bit =
339 stateField[currState].effecter_state - (8 * bitfieldIndex);
340 if (states->possible_states_size < bitfieldIndex ||
341 !(states->states[bitfieldIndex].byte & (1 << bit)))
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600342 {
George Liu1ec85d42020-02-12 16:05:32 +0800343 std::cerr
344 << "Invalid state set value, EFFECTER_ID=" << effecterId
345 << " VALUE=" << stateField[currState].effecter_state
346 << " COMPOSITE_EFFECTER_ID=" << currState
347 << " DBUS_PATH=" << dbusMappings[currState].objectPath
348 << "\n";
349 rc = PLDM_PLATFORM_SET_EFFECTER_UNSUPPORTED_SENSORSTATE;
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600350 break;
351 }
George Liu1ec85d42020-02-12 16:05:32 +0800352 const DBusMapping& dbusMapping = dbusMappings[currState];
353 const StatestoDbusVal& dbusValToMap = dbusValMaps[currState];
354
355 if (stateField[currState].set_request == PLDM_REQUEST_SET)
356 {
357 try
358 {
359 dBusIntf.setDbusProperty(
360 dbusMapping,
361 dbusValToMap.at(
362 stateField[currState].effecter_state));
363 }
364 catch (const std::exception& e)
365 {
366 std::cerr
367 << "Error setting property, ERROR=" << e.what()
368 << " PROPERTY=" << dbusMapping.propertyName
369 << " INTERFACE="
370 << dbusMapping.interface << " PATH="
371 << dbusMapping.objectPath << "\n";
372 return PLDM_ERROR;
373 }
374 }
375 uint8_t* nextState =
376 reinterpret_cast<uint8_t*>(states) +
377 sizeof(state_effecter_possible_states) -
378 sizeof(states->states) +
379 (states->possible_states_size * sizeof(states->states));
380 states = reinterpret_cast<state_effecter_possible_states*>(
381 nextState);
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600382 }
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600383 }
George Liu1ec85d42020-02-12 16:05:32 +0800384 catch (const std::out_of_range& e)
385 {
386 std::cerr << "the effecterId does not exist. effecter id: "
387 << effecterId << e.what() << '\n';
388 }
389
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600390 return rc;
391 }
Deepak Kodihallic682fe22020-03-04 00:42:54 -0600392
393 private:
394 pdr_utils::Repo pdrRepo;
395 uint16_t nextEffecterId{};
George Liu1ec85d42020-02-12 16:05:32 +0800396 DbusObjMaps dbusObjMaps{};
Pavithra Barithaya51efaf82020-04-02 02:42:27 -0500397 HostPDRHandler* hostPDRHandler;
TOM JOSEPHd4d97a52020-03-23 14:36:34 +0530398 events::StateSensorHandler stateSensorHandler;
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600399};
400
401} // namespace platform
Deepak Kodihalli557dfb02019-05-12 13:11:17 +0530402} // namespace responder
403} // namespace pldm