blob: ad635bd2d2b30120caf33174761e6e313df764e5 [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 =
31 std::function<void(const Json& json, pdr_utils::RepoInterface& repo)>;
32
George Liu1ec85d42020-02-12 16:05:32 +080033using EffecterId = uint16_t;
George Liua2870722020-02-11 11:09:30 +080034using DbusObjMaps =
35 std::map<EffecterId,
36 std::tuple<pdr_utils::DbusMappings, pdr_utils::DbusValMaps>>;
Tom Joseph56e45c52020-03-16 10:01:45 +053037using DbusPath = std::string;
38using EffecterObjs = std::vector<DbusPath>;
39using EventType = uint8_t;
40using EventHandler = std::function<int(
41 const pldm_msg* request, size_t payloadLength, uint8_t formatVersion,
42 uint8_t tid, size_t eventDataOffset)>;
43using EventHandlers = std::vector<EventHandler>;
44using EventMap = std::map<EventType, EventHandlers>;
Deepak Kodihallic682fe22020-03-04 00:42:54 -060045
Zahed Hossain75330f32020-03-24 02:15:03 -050046// EventEntry = <uint8_t> - EventState <uint8_t> - SensorOffset <uint16_t> -
47// SensorID
48using EventEntry = uint32_t;
49struct DBusInfo
50{
51 pldm::utils::DBusMapping dBusValues;
52 pldm::utils::PropertyValue dBusPropertyValue;
53};
54
Deepak Kodihallibc669f12019-11-28 08:52:07 -060055class Handler : public CmdHandler
Sampa Misraa2fa0702019-05-31 01:28:55 -050056{
Deepak Kodihallibc669f12019-11-28 08:52:07 -060057 public:
TOM JOSEPHd4d97a52020-03-23 14:36:34 +053058 Handler(const std::string& pdrJsonsDir, const std::string& eventsJsonsDir,
59 pldm_pdr* repo, HostPDRHandler* hostPDRHandler,
Tom Joseph33e9c7e2020-06-11 22:09:52 +053060 fru::Handler* fruHandler,
Tom Joseph56e45c52020-03-16 10:01:45 +053061 const std::optional<EventMap>& addOnHandlersMap = std::nullopt) :
Pavithra Barithaya51efaf82020-04-02 02:42:27 -050062 pdrRepo(repo),
Tom Joseph33e9c7e2020-06-11 22:09:52 +053063 hostPDRHandler(hostPDRHandler), stateSensorHandler(eventsJsonsDir),
64 fruHandler(fruHandler)
Sampa Misraa2fa0702019-05-31 01:28:55 -050065 {
TOM JOSEPHd4d97a52020-03-23 14:36:34 +053066 generate(pdrJsonsDir, pdrRepo);
Deepak Kodihallic682fe22020-03-04 00:42:54 -060067
Deepak Kodihallibc669f12019-11-28 08:52:07 -060068 handlers.emplace(PLDM_GET_PDR,
69 [this](const pldm_msg* request, size_t payloadLength) {
70 return this->getPDR(request, payloadLength);
71 });
George Liueccb0c52020-01-14 11:09:56 +080072 handlers.emplace(PLDM_SET_NUMERIC_EFFECTER_VALUE,
73 [this](const pldm_msg* request, size_t payloadLength) {
74 return this->setNumericEffecterValue(
75 request, payloadLength);
76 });
Deepak Kodihallibc669f12019-11-28 08:52:07 -060077 handlers.emplace(PLDM_SET_STATE_EFFECTER_STATES,
78 [this](const pldm_msg* request, size_t payloadLength) {
79 return this->setStateEffecterStates(request,
80 payloadLength);
81 });
Tom Joseph56e45c52020-03-16 10:01:45 +053082 handlers.emplace(PLDM_PLATFORM_EVENT_MESSAGE,
83 [this](const pldm_msg* request, size_t payloadLength) {
84 return this->platformEventMessage(request,
85 payloadLength);
86 });
87
88 // Default handler for PLDM Events
89 eventHandlers[PLDM_SENSOR_EVENT].emplace_back(
90 [this](const pldm_msg* request, size_t payloadLength,
91 uint8_t formatVersion, uint8_t tid, size_t eventDataOffset) {
92 return this->sensorEvent(request, payloadLength, formatVersion,
93 tid, eventDataOffset);
94 });
Deepak Kodihalli8cb6f662020-04-10 02:55:43 -050095 eventHandlers[PLDM_PDR_REPOSITORY_CHG_EVENT].emplace_back(
96 [this](const pldm_msg* request, size_t payloadLength,
97 uint8_t formatVersion, uint8_t tid, size_t eventDataOffset) {
98 return this->pldmPDRRepositoryChgEvent(request, payloadLength,
99 formatVersion, tid,
100 eventDataOffset);
101 });
Tom Joseph56e45c52020-03-16 10:01:45 +0530102
103 // Additional OEM event handlers for PLDM events, append it to the
104 // standard handlers
105 if (addOnHandlersMap)
106 {
107 auto addOnHandlers = addOnHandlersMap.value();
108 for (EventMap::iterator iter = addOnHandlers.begin();
109 iter != addOnHandlers.end(); ++iter)
110 {
111 auto search = eventHandlers.find(iter->first);
112 if (search != eventHandlers.end())
113 {
114 search->second.insert(std::end(search->second),
115 std::begin(iter->second),
116 std::end(iter->second));
117 }
118 else
119 {
120 eventHandlers.emplace(iter->first, iter->second);
121 }
122 }
123 }
Sampa Misraa2fa0702019-05-31 01:28:55 -0500124 }
125
George Liu1ec85d42020-02-12 16:05:32 +0800126 pdr_utils::Repo& getRepo()
Deepak Kodihallic682fe22020-03-04 00:42:54 -0600127 {
George Liu1ec85d42020-02-12 16:05:32 +0800128 return this->pdrRepo;
Deepak Kodihallic682fe22020-03-04 00:42:54 -0600129 }
130
George Liu1ec85d42020-02-12 16:05:32 +0800131 /** @brief Add D-Bus mapping and value mapping(stateId to D-Bus) for the
132 * effecterId. If the same id is added, the previous dbusObjs will
133 * be "over-written".
134 *
135 * @param[in] effecterId - effecter id
136 * @param[in] dbusObj - list of D-Bus object structure and list of D-Bus
137 * property value to attribute value
138 */
George Liua2870722020-02-11 11:09:30 +0800139 void addDbusObjMaps(
140 uint16_t effecterId,
141 std::tuple<pdr_utils::DbusMappings, pdr_utils::DbusValMaps> dbusObj);
George Liu1ec85d42020-02-12 16:05:32 +0800142
143 /** @brief Retrieve an effecter id -> D-Bus objects mapping
144 *
145 * @param[in] effecterId - effecter id
146 *
George Liua2870722020-02-11 11:09:30 +0800147 * @return std::tuple<pdr_utils::DbusMappings, pdr_utils::DbusValMaps> -
148 * list of D-Bus object structure and list of D-Bus property value
149 * to attribute value
George Liu1ec85d42020-02-12 16:05:32 +0800150 */
George Liua2870722020-02-11 11:09:30 +0800151 const std::tuple<pdr_utils::DbusMappings, pdr_utils::DbusValMaps>&
George Liu1ec85d42020-02-12 16:05:32 +0800152 getDbusObjMaps(uint16_t effecterId) const;
Deepak Kodihallic682fe22020-03-04 00:42:54 -0600153
154 uint16_t getNextEffecterId()
155 {
156 return ++nextEffecterId;
157 }
158
159 /** @brief Parse PDR JSONs and build PDR repository
160 *
161 * @param[in] dir - directory housing platform specific PDR JSON files
162 * @param[in] repo - instance of concrete implementation of Repo
163 */
164 void generate(const std::string& dir, Repo& repo);
165
166 /** @brief Parse PDR JSONs and build state effecter PDR repository
167 *
168 * @param[in] json - platform specific PDR JSON files
169 * @param[in] repo - instance of state effecter implementation of Repo
170 */
171 void generateStateEffecterRepo(const Json& json, Repo& repo);
172
Tom Joseph56e45c52020-03-16 10:01:45 +0530173 /** @brief map of PLDM event type to EventHandlers
174 *
175 */
176 EventMap eventHandlers;
177
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600178 /** @brief Handler for GetPDR
179 *
180 * @param[in] request - Request message payload
181 * @param[in] payloadLength - Request payload length
182 * @param[out] Response - Response message written here
183 */
184 Response getPDR(const pldm_msg* request, size_t payloadLength);
Sampa Misraa2fa0702019-05-31 01:28:55 -0500185
George Liueccb0c52020-01-14 11:09:56 +0800186 /** @brief Handler for setNumericEffecterValue
187 *
188 * @param[in] request - Request message
189 * @param[in] payloadLength - Request payload length
190 * @return Response - PLDM Response message
191 */
192 Response setNumericEffecterValue(const pldm_msg* request,
193 size_t payloadLength);
194
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600195 /** @brief Handler for setStateEffecterStates
196 *
197 * @param[in] request - Request message
198 * @param[in] payloadLength - Request payload length
199 * @return Response - PLDM Response message
200 */
201 Response setStateEffecterStates(const pldm_msg* request,
202 size_t payloadLength);
203
Tom Joseph56e45c52020-03-16 10:01:45 +0530204 /** @brief Handler for PlatformEventMessage
205 *
206 * @param[in] request - Request message
207 * @param[in] payloadLength - Request payload length
208 * @return Response - PLDM Response message
209 */
210 Response platformEventMessage(const pldm_msg* request,
211 size_t payloadLength);
212
213 /** @brief Handler for event class Sensor event
214 *
215 * @param[in] request - Request message
216 * @param[in] payloadLength - Request payload length
217 * @param[in] formatVersion - Version of the event format
218 * @param[in] tid - Terminus ID of the event's originator
219 * @param[in] eventDataOffset - Offset of the event data in the request
220 * message
221 * @return PLDM completion code
222 */
223 int sensorEvent(const pldm_msg* request, size_t payloadLength,
224 uint8_t formatVersion, uint8_t tid, size_t eventDataOffset);
225
Deepak Kodihalli8cb6f662020-04-10 02:55:43 -0500226 /** @brief Handler for pldmPDRRepositoryChgEvent
227 *
228 * @param[in] request - Request message
229 * @param[in] payloadLength - Request payload length
230 * @param[in] formatVersion - Version of the event format
231 * @param[in] tid - Terminus ID of the event's originator
232 * @param[in] eventDataOffset - Offset of the event data in the request
233 * message
234 * @return PLDM completion code
235 */
236 int pldmPDRRepositoryChgEvent(const pldm_msg* request, size_t payloadLength,
237 uint8_t formatVersion, uint8_t tid,
238 size_t eventDataOffset);
239
240 /** @brief Handler for extracting the PDR handles from changeEntries
241 *
242 * @param[in] changeEntryData - ChangeEntry data from changeRecord
243 * @param[in] changeEntryDataSize - total size of changeEntryData
244 * @param[in] numberOfChangeEntries - total number of changeEntries to
245 * extract
246 * @param[out] pdrRecordHandles - std::vector where the extracted PDR
247 * handles are placed
248 * @return PLDM completion code
249 */
250 int getPDRRecordHandles(const ChangeEntry* changeEntryData,
251 size_t changeEntryDataSize,
252 size_t numberOfChangeEntries,
253 PDRRecordHandles& pdrRecordHandles);
254
Zahed Hossain75330f32020-03-24 02:15:03 -0500255 /** @brief Handler for setting Sensor event data
256 *
257 * @param[in] sensorId - sensorID value of the sensor
258 * @param[in] sensorOffset - Identifies which state sensor within a
259 * composite state sensor the event is being returned for
260 * @param[in] eventState - The event state value from the state change that
261 * triggered the event message
262 * @return PLDM completion code
263 */
264 int setSensorEventData(uint16_t sensorId, uint8_t sensorOffset,
265 uint8_t eventState);
266
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600267 /** @brief Function to set the effecter requested by pldm requester
268 * @param[in] dBusIntf - The interface object
269 * @param[in] effecterId - Effecter ID sent by the requester to act on
270 * @param[in] stateField - The state field data for each of the states,
271 * equal to composite effecter count in number
272 * @return - Success or failure in setting the states. Returns failure in
273 * terms of PLDM completion codes if atleast one state fails to be set
274 */
275 template <class DBusInterface>
276 int setStateEffecterStatesHandler(
Deepak Kodihallic682fe22020-03-04 00:42:54 -0600277 const DBusInterface& dBusIntf, uint16_t effecterId,
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600278 const std::vector<set_effecter_state_field>& stateField)
Sampa Misraa2fa0702019-05-31 01:28:55 -0500279 {
George Liue53193f2020-02-24 09:23:26 +0800280 using namespace pldm::responder::pdr;
George Liu1e44c732020-02-28 20:20:06 +0800281 using namespace pldm::utils;
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600282 using StateSetNum = uint8_t;
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600283
284 state_effecter_possible_states* states = nullptr;
285 pldm_state_effecter_pdr* pdr = nullptr;
286 uint8_t compEffecterCnt = stateField.size();
George Liu1ec85d42020-02-12 16:05:32 +0800287
288 std::unique_ptr<pldm_pdr, decltype(&pldm_pdr_destroy)>
289 stateEffecterPdrRepo(pldm_pdr_init(), pldm_pdr_destroy);
290 Repo stateEffecterPDRs(stateEffecterPdrRepo.get());
291 getRepoByType(pdrRepo, stateEffecterPDRs, PLDM_STATE_EFFECTER_PDR);
292 if (stateEffecterPDRs.empty())
293 {
294 std::cerr << "Failed to get record by PDR type\n";
295 return PLDM_PLATFORM_INVALID_EFFECTER_ID;
296 }
297
George Liue53193f2020-02-24 09:23:26 +0800298 PdrEntry pdrEntry{};
George Liu1ec85d42020-02-12 16:05:32 +0800299 auto pdrRecord = stateEffecterPDRs.getFirstRecord(pdrEntry);
George Liue53193f2020-02-24 09:23:26 +0800300 while (pdrRecord)
301 {
302 pdr = reinterpret_cast<pldm_state_effecter_pdr*>(pdrEntry.data);
303 if (pdr->effecter_id != effecterId)
Sampa Misraa2fa0702019-05-31 01:28:55 -0500304 {
George Liue53193f2020-02-24 09:23:26 +0800305 pdr = nullptr;
George Liu1ec85d42020-02-12 16:05:32 +0800306 pdrRecord =
307 stateEffecterPDRs.getNextRecord(pdrRecord, pdrEntry);
George Liue53193f2020-02-24 09:23:26 +0800308 continue;
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600309 }
George Liue53193f2020-02-24 09:23:26 +0800310
311 states = reinterpret_cast<state_effecter_possible_states*>(
312 pdr->possible_states);
313 if (compEffecterCnt > pdr->composite_effecter_count)
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600314 {
George Liue53193f2020-02-24 09:23:26 +0800315 std::cerr << "The requester sent wrong composite effecter"
316 << " count for the effecter, EFFECTER_ID="
317 << effecterId << "COMP_EFF_CNT=" << compEffecterCnt
318 << "\n";
319 return PLDM_ERROR_INVALID_DATA;
Sampa Misraa2fa0702019-05-31 01:28:55 -0500320 }
George Liue53193f2020-02-24 09:23:26 +0800321 break;
322 }
323
324 if (!pdr)
325 {
326 return PLDM_PLATFORM_INVALID_EFFECTER_ID;
Sampa Misraa2fa0702019-05-31 01:28:55 -0500327 }
Sampa Misraa2fa0702019-05-31 01:28:55 -0500328
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600329 int rc = PLDM_SUCCESS;
George Liu1ec85d42020-02-12 16:05:32 +0800330 try
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600331 {
George Liu1ec85d42020-02-12 16:05:32 +0800332 const auto& [dbusMappings, dbusValMaps] =
333 dbusObjMaps.at(effecterId);
334 for (uint8_t currState = 0; currState < compEffecterCnt;
335 ++currState)
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600336 {
George Liu1ec85d42020-02-12 16:05:32 +0800337 std::vector<StateSetNum> allowed{};
338 // computation is based on table 79 from DSP0248 v1.1.1
339 uint8_t bitfieldIndex =
340 stateField[currState].effecter_state / 8;
341 uint8_t bit =
342 stateField[currState].effecter_state - (8 * bitfieldIndex);
343 if (states->possible_states_size < bitfieldIndex ||
344 !(states->states[bitfieldIndex].byte & (1 << bit)))
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600345 {
George Liu1ec85d42020-02-12 16:05:32 +0800346 std::cerr
347 << "Invalid state set value, EFFECTER_ID=" << effecterId
348 << " VALUE=" << stateField[currState].effecter_state
349 << " COMPOSITE_EFFECTER_ID=" << currState
350 << " DBUS_PATH=" << dbusMappings[currState].objectPath
351 << "\n";
352 rc = PLDM_PLATFORM_SET_EFFECTER_UNSUPPORTED_SENSORSTATE;
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600353 break;
354 }
George Liu1ec85d42020-02-12 16:05:32 +0800355 const DBusMapping& dbusMapping = dbusMappings[currState];
356 const StatestoDbusVal& dbusValToMap = dbusValMaps[currState];
357
358 if (stateField[currState].set_request == PLDM_REQUEST_SET)
359 {
360 try
361 {
362 dBusIntf.setDbusProperty(
363 dbusMapping,
364 dbusValToMap.at(
365 stateField[currState].effecter_state));
366 }
367 catch (const std::exception& e)
368 {
369 std::cerr
370 << "Error setting property, ERROR=" << e.what()
371 << " PROPERTY=" << dbusMapping.propertyName
372 << " INTERFACE="
373 << dbusMapping.interface << " PATH="
374 << dbusMapping.objectPath << "\n";
375 return PLDM_ERROR;
376 }
377 }
378 uint8_t* nextState =
379 reinterpret_cast<uint8_t*>(states) +
380 sizeof(state_effecter_possible_states) -
381 sizeof(states->states) +
382 (states->possible_states_size * sizeof(states->states));
383 states = reinterpret_cast<state_effecter_possible_states*>(
384 nextState);
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600385 }
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600386 }
George Liu1ec85d42020-02-12 16:05:32 +0800387 catch (const std::out_of_range& e)
388 {
389 std::cerr << "the effecterId does not exist. effecter id: "
390 << effecterId << e.what() << '\n';
391 }
392
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600393 return rc;
394 }
Deepak Kodihallic682fe22020-03-04 00:42:54 -0600395
396 private:
397 pdr_utils::Repo pdrRepo;
398 uint16_t nextEffecterId{};
George Liu1ec85d42020-02-12 16:05:32 +0800399 DbusObjMaps dbusObjMaps{};
Pavithra Barithaya51efaf82020-04-02 02:42:27 -0500400 HostPDRHandler* hostPDRHandler;
TOM JOSEPHd4d97a52020-03-23 14:36:34 +0530401 events::StateSensorHandler stateSensorHandler;
Tom Joseph33e9c7e2020-06-11 22:09:52 +0530402 fru::Handler* fruHandler;
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600403};
404
405} // namespace platform
Deepak Kodihalli557dfb02019-05-12 13:11:17 +0530406} // namespace responder
407} // namespace pldm