blob: 1982031131160e79b3a6adad30d7db8678d7457f [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
Deepak Kodihallibc669f12019-11-28 08:52:07 -06005#include "handler.hpp"
Pavithra Barithaya51efaf82020-04-02 02:42:27 -05006#include "host_pdr_handler.hpp"
Sampa Misraa2fa0702019-05-31 01:28:55 -05007#include "libpldmresponder/pdr.hpp"
George Liue53193f2020-02-24 09:23:26 +08008#include "libpldmresponder/pdr_utils.hpp"
George Liu83409572019-12-24 18:42:54 +08009#include "utils.hpp"
Sampa Misraa2fa0702019-05-31 01:28:55 -050010
Deepak Kodihalli557dfb02019-05-12 13:11:17 +053011#include <stdint.h>
12
Sampa Misraa2fa0702019-05-31 01:28:55 -050013#include <map>
Deepak Kodihalli557dfb02019-05-12 13:11:17 +053014
15#include "libpldm/platform.h"
Sampa Misraa2fa0702019-05-31 01:28:55 -050016#include "libpldm/states.h"
Deepak Kodihalli557dfb02019-05-12 13:11:17 +053017
18namespace pldm
19{
Deepak Kodihalli557dfb02019-05-12 13:11:17 +053020namespace responder
21{
Sampa Misraa2fa0702019-05-31 01:28:55 -050022namespace platform
23{
24
George Liu1ec85d42020-02-12 16:05:32 +080025using namespace pldm::utils;
26using namespace pldm::responder::pdr_utils;
27
George Liua2870722020-02-11 11:09:30 +080028using generatePDR =
29 std::function<void(const Json& json, pdr_utils::RepoInterface& repo)>;
30
George Liu1ec85d42020-02-12 16:05:32 +080031using EffecterId = uint16_t;
George Liua2870722020-02-11 11:09:30 +080032using DbusObjMaps =
33 std::map<EffecterId,
34 std::tuple<pdr_utils::DbusMappings, pdr_utils::DbusValMaps>>;
Tom Joseph56e45c52020-03-16 10:01:45 +053035using DbusPath = std::string;
36using EffecterObjs = std::vector<DbusPath>;
37using EventType = uint8_t;
38using EventHandler = std::function<int(
39 const pldm_msg* request, size_t payloadLength, uint8_t formatVersion,
40 uint8_t tid, size_t eventDataOffset)>;
41using EventHandlers = std::vector<EventHandler>;
42using EventMap = std::map<EventType, EventHandlers>;
Deepak Kodihallic682fe22020-03-04 00:42:54 -060043
Zahed Hossain75330f32020-03-24 02:15:03 -050044// EventEntry = <uint8_t> - EventState <uint8_t> - SensorOffset <uint16_t> -
45// SensorID
46using EventEntry = uint32_t;
47struct DBusInfo
48{
49 pldm::utils::DBusMapping dBusValues;
50 pldm::utils::PropertyValue dBusPropertyValue;
51};
52
Deepak Kodihallibc669f12019-11-28 08:52:07 -060053class Handler : public CmdHandler
Sampa Misraa2fa0702019-05-31 01:28:55 -050054{
Deepak Kodihallibc669f12019-11-28 08:52:07 -060055 public:
Tom Joseph56e45c52020-03-16 10:01:45 +053056 Handler(const std::string& dir, pldm_pdr* repo,
Pavithra Barithaya51efaf82020-04-02 02:42:27 -050057 HostPDRHandler* hostPDRHandler,
Tom Joseph56e45c52020-03-16 10:01:45 +053058 const std::optional<EventMap>& addOnHandlersMap = std::nullopt) :
Pavithra Barithaya51efaf82020-04-02 02:42:27 -050059 pdrRepo(repo),
60 hostPDRHandler(hostPDRHandler)
Sampa Misraa2fa0702019-05-31 01:28:55 -050061 {
Deepak Kodihallic682fe22020-03-04 00:42:54 -060062 generate(dir, pdrRepo);
63
Deepak Kodihallibc669f12019-11-28 08:52:07 -060064 handlers.emplace(PLDM_GET_PDR,
65 [this](const pldm_msg* request, size_t payloadLength) {
66 return this->getPDR(request, payloadLength);
67 });
George Liueccb0c52020-01-14 11:09:56 +080068 handlers.emplace(PLDM_SET_NUMERIC_EFFECTER_VALUE,
69 [this](const pldm_msg* request, size_t payloadLength) {
70 return this->setNumericEffecterValue(
71 request, payloadLength);
72 });
Deepak Kodihallibc669f12019-11-28 08:52:07 -060073 handlers.emplace(PLDM_SET_STATE_EFFECTER_STATES,
74 [this](const pldm_msg* request, size_t payloadLength) {
75 return this->setStateEffecterStates(request,
76 payloadLength);
77 });
Tom Joseph56e45c52020-03-16 10:01:45 +053078 handlers.emplace(PLDM_PLATFORM_EVENT_MESSAGE,
79 [this](const pldm_msg* request, size_t payloadLength) {
80 return this->platformEventMessage(request,
81 payloadLength);
82 });
83
84 // Default handler for PLDM Events
85 eventHandlers[PLDM_SENSOR_EVENT].emplace_back(
86 [this](const pldm_msg* request, size_t payloadLength,
87 uint8_t formatVersion, uint8_t tid, size_t eventDataOffset) {
88 return this->sensorEvent(request, payloadLength, formatVersion,
89 tid, eventDataOffset);
90 });
Deepak Kodihalli8cb6f662020-04-10 02:55:43 -050091 eventHandlers[PLDM_PDR_REPOSITORY_CHG_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->pldmPDRRepositoryChgEvent(request, payloadLength,
95 formatVersion, tid,
96 eventDataOffset);
97 });
Tom Joseph56e45c52020-03-16 10:01:45 +053098
99 // Additional OEM event handlers for PLDM events, append it to the
100 // standard handlers
101 if (addOnHandlersMap)
102 {
103 auto addOnHandlers = addOnHandlersMap.value();
104 for (EventMap::iterator iter = addOnHandlers.begin();
105 iter != addOnHandlers.end(); ++iter)
106 {
107 auto search = eventHandlers.find(iter->first);
108 if (search != eventHandlers.end())
109 {
110 search->second.insert(std::end(search->second),
111 std::begin(iter->second),
112 std::end(iter->second));
113 }
114 else
115 {
116 eventHandlers.emplace(iter->first, iter->second);
117 }
118 }
119 }
Sampa Misraa2fa0702019-05-31 01:28:55 -0500120 }
121
George Liu1ec85d42020-02-12 16:05:32 +0800122 pdr_utils::Repo& getRepo()
Deepak Kodihallic682fe22020-03-04 00:42:54 -0600123 {
George Liu1ec85d42020-02-12 16:05:32 +0800124 return this->pdrRepo;
Deepak Kodihallic682fe22020-03-04 00:42:54 -0600125 }
126
George Liu1ec85d42020-02-12 16:05:32 +0800127 /** @brief Add D-Bus mapping and value mapping(stateId to D-Bus) for the
128 * effecterId. If the same id is added, the previous dbusObjs will
129 * be "over-written".
130 *
131 * @param[in] effecterId - effecter id
132 * @param[in] dbusObj - list of D-Bus object structure and list of D-Bus
133 * property value to attribute value
134 */
George Liua2870722020-02-11 11:09:30 +0800135 void addDbusObjMaps(
136 uint16_t effecterId,
137 std::tuple<pdr_utils::DbusMappings, pdr_utils::DbusValMaps> dbusObj);
George Liu1ec85d42020-02-12 16:05:32 +0800138
139 /** @brief Retrieve an effecter id -> D-Bus objects mapping
140 *
141 * @param[in] effecterId - effecter id
142 *
George Liua2870722020-02-11 11:09:30 +0800143 * @return std::tuple<pdr_utils::DbusMappings, pdr_utils::DbusValMaps> -
144 * list of D-Bus object structure and list of D-Bus property value
145 * to attribute value
George Liu1ec85d42020-02-12 16:05:32 +0800146 */
George Liua2870722020-02-11 11:09:30 +0800147 const std::tuple<pdr_utils::DbusMappings, pdr_utils::DbusValMaps>&
George Liu1ec85d42020-02-12 16:05:32 +0800148 getDbusObjMaps(uint16_t effecterId) const;
Deepak Kodihallic682fe22020-03-04 00:42:54 -0600149
150 uint16_t getNextEffecterId()
151 {
152 return ++nextEffecterId;
153 }
154
155 /** @brief Parse PDR JSONs and build PDR repository
156 *
157 * @param[in] dir - directory housing platform specific PDR JSON files
158 * @param[in] repo - instance of concrete implementation of Repo
159 */
160 void generate(const std::string& dir, Repo& repo);
161
162 /** @brief Parse PDR JSONs and build state effecter PDR repository
163 *
164 * @param[in] json - platform specific PDR JSON files
165 * @param[in] repo - instance of state effecter implementation of Repo
166 */
167 void generateStateEffecterRepo(const Json& json, Repo& repo);
168
Tom Joseph56e45c52020-03-16 10:01:45 +0530169 /** @brief map of PLDM event type to EventHandlers
170 *
171 */
172 EventMap eventHandlers;
173
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600174 /** @brief Handler for GetPDR
175 *
176 * @param[in] request - Request message payload
177 * @param[in] payloadLength - Request payload length
178 * @param[out] Response - Response message written here
179 */
180 Response getPDR(const pldm_msg* request, size_t payloadLength);
Sampa Misraa2fa0702019-05-31 01:28:55 -0500181
George Liueccb0c52020-01-14 11:09:56 +0800182 /** @brief Handler for setNumericEffecterValue
183 *
184 * @param[in] request - Request message
185 * @param[in] payloadLength - Request payload length
186 * @return Response - PLDM Response message
187 */
188 Response setNumericEffecterValue(const pldm_msg* request,
189 size_t payloadLength);
190
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600191 /** @brief Handler for setStateEffecterStates
192 *
193 * @param[in] request - Request message
194 * @param[in] payloadLength - Request payload length
195 * @return Response - PLDM Response message
196 */
197 Response setStateEffecterStates(const pldm_msg* request,
198 size_t payloadLength);
199
Tom Joseph56e45c52020-03-16 10:01:45 +0530200 /** @brief Handler for PlatformEventMessage
201 *
202 * @param[in] request - Request message
203 * @param[in] payloadLength - Request payload length
204 * @return Response - PLDM Response message
205 */
206 Response platformEventMessage(const pldm_msg* request,
207 size_t payloadLength);
208
209 /** @brief Handler for event class Sensor event
210 *
211 * @param[in] request - Request message
212 * @param[in] payloadLength - Request payload length
213 * @param[in] formatVersion - Version of the event format
214 * @param[in] tid - Terminus ID of the event's originator
215 * @param[in] eventDataOffset - Offset of the event data in the request
216 * message
217 * @return PLDM completion code
218 */
219 int sensorEvent(const pldm_msg* request, size_t payloadLength,
220 uint8_t formatVersion, uint8_t tid, size_t eventDataOffset);
221
Deepak Kodihalli8cb6f662020-04-10 02:55:43 -0500222 /** @brief Handler for pldmPDRRepositoryChgEvent
223 *
224 * @param[in] request - Request message
225 * @param[in] payloadLength - Request payload length
226 * @param[in] formatVersion - Version of the event format
227 * @param[in] tid - Terminus ID of the event's originator
228 * @param[in] eventDataOffset - Offset of the event data in the request
229 * message
230 * @return PLDM completion code
231 */
232 int pldmPDRRepositoryChgEvent(const pldm_msg* request, size_t payloadLength,
233 uint8_t formatVersion, uint8_t tid,
234 size_t eventDataOffset);
235
236 /** @brief Handler for extracting the PDR handles from changeEntries
237 *
238 * @param[in] changeEntryData - ChangeEntry data from changeRecord
239 * @param[in] changeEntryDataSize - total size of changeEntryData
240 * @param[in] numberOfChangeEntries - total number of changeEntries to
241 * extract
242 * @param[out] pdrRecordHandles - std::vector where the extracted PDR
243 * handles are placed
244 * @return PLDM completion code
245 */
246 int getPDRRecordHandles(const ChangeEntry* changeEntryData,
247 size_t changeEntryDataSize,
248 size_t numberOfChangeEntries,
249 PDRRecordHandles& pdrRecordHandles);
250
Zahed Hossain75330f32020-03-24 02:15:03 -0500251 /** @brief Handler for setting Sensor event data
252 *
253 * @param[in] sensorId - sensorID value of the sensor
254 * @param[in] sensorOffset - Identifies which state sensor within a
255 * composite state sensor the event is being returned for
256 * @param[in] eventState - The event state value from the state change that
257 * triggered the event message
258 * @return PLDM completion code
259 */
260 int setSensorEventData(uint16_t sensorId, uint8_t sensorOffset,
261 uint8_t eventState);
262
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600263 /** @brief Function to set the effecter requested by pldm requester
264 * @param[in] dBusIntf - The interface object
265 * @param[in] effecterId - Effecter ID sent by the requester to act on
266 * @param[in] stateField - The state field data for each of the states,
267 * equal to composite effecter count in number
268 * @return - Success or failure in setting the states. Returns failure in
269 * terms of PLDM completion codes if atleast one state fails to be set
270 */
271 template <class DBusInterface>
272 int setStateEffecterStatesHandler(
Deepak Kodihallic682fe22020-03-04 00:42:54 -0600273 const DBusInterface& dBusIntf, uint16_t effecterId,
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600274 const std::vector<set_effecter_state_field>& stateField)
Sampa Misraa2fa0702019-05-31 01:28:55 -0500275 {
George Liue53193f2020-02-24 09:23:26 +0800276 using namespace pldm::responder::pdr;
George Liu1e44c732020-02-28 20:20:06 +0800277 using namespace pldm::utils;
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600278 using StateSetNum = uint8_t;
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600279
280 state_effecter_possible_states* states = nullptr;
281 pldm_state_effecter_pdr* pdr = nullptr;
282 uint8_t compEffecterCnt = stateField.size();
George Liu1ec85d42020-02-12 16:05:32 +0800283
284 std::unique_ptr<pldm_pdr, decltype(&pldm_pdr_destroy)>
285 stateEffecterPdrRepo(pldm_pdr_init(), pldm_pdr_destroy);
286 Repo stateEffecterPDRs(stateEffecterPdrRepo.get());
287 getRepoByType(pdrRepo, stateEffecterPDRs, PLDM_STATE_EFFECTER_PDR);
288 if (stateEffecterPDRs.empty())
289 {
290 std::cerr << "Failed to get record by PDR type\n";
291 return PLDM_PLATFORM_INVALID_EFFECTER_ID;
292 }
293
George Liue53193f2020-02-24 09:23:26 +0800294 PdrEntry pdrEntry{};
George Liu1ec85d42020-02-12 16:05:32 +0800295 auto pdrRecord = stateEffecterPDRs.getFirstRecord(pdrEntry);
George Liue53193f2020-02-24 09:23:26 +0800296 while (pdrRecord)
297 {
298 pdr = reinterpret_cast<pldm_state_effecter_pdr*>(pdrEntry.data);
299 if (pdr->effecter_id != effecterId)
Sampa Misraa2fa0702019-05-31 01:28:55 -0500300 {
George Liue53193f2020-02-24 09:23:26 +0800301 pdr = nullptr;
George Liu1ec85d42020-02-12 16:05:32 +0800302 pdrRecord =
303 stateEffecterPDRs.getNextRecord(pdrRecord, pdrEntry);
George Liue53193f2020-02-24 09:23:26 +0800304 continue;
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600305 }
George Liue53193f2020-02-24 09:23:26 +0800306
307 states = reinterpret_cast<state_effecter_possible_states*>(
308 pdr->possible_states);
309 if (compEffecterCnt > pdr->composite_effecter_count)
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600310 {
George Liue53193f2020-02-24 09:23:26 +0800311 std::cerr << "The requester sent wrong composite effecter"
312 << " count for the effecter, EFFECTER_ID="
313 << effecterId << "COMP_EFF_CNT=" << compEffecterCnt
314 << "\n";
315 return PLDM_ERROR_INVALID_DATA;
Sampa Misraa2fa0702019-05-31 01:28:55 -0500316 }
George Liue53193f2020-02-24 09:23:26 +0800317 break;
318 }
319
320 if (!pdr)
321 {
322 return PLDM_PLATFORM_INVALID_EFFECTER_ID;
Sampa Misraa2fa0702019-05-31 01:28:55 -0500323 }
Sampa Misraa2fa0702019-05-31 01:28:55 -0500324
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600325 int rc = PLDM_SUCCESS;
George Liu1ec85d42020-02-12 16:05:32 +0800326 try
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600327 {
George Liu1ec85d42020-02-12 16:05:32 +0800328 const auto& [dbusMappings, dbusValMaps] =
329 dbusObjMaps.at(effecterId);
330 for (uint8_t currState = 0; currState < compEffecterCnt;
331 ++currState)
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600332 {
George Liu1ec85d42020-02-12 16:05:32 +0800333 std::vector<StateSetNum> allowed{};
334 // computation is based on table 79 from DSP0248 v1.1.1
335 uint8_t bitfieldIndex =
336 stateField[currState].effecter_state / 8;
337 uint8_t bit =
338 stateField[currState].effecter_state - (8 * bitfieldIndex);
339 if (states->possible_states_size < bitfieldIndex ||
340 !(states->states[bitfieldIndex].byte & (1 << bit)))
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600341 {
George Liu1ec85d42020-02-12 16:05:32 +0800342 std::cerr
343 << "Invalid state set value, EFFECTER_ID=" << effecterId
344 << " VALUE=" << stateField[currState].effecter_state
345 << " COMPOSITE_EFFECTER_ID=" << currState
346 << " DBUS_PATH=" << dbusMappings[currState].objectPath
347 << "\n";
348 rc = PLDM_PLATFORM_SET_EFFECTER_UNSUPPORTED_SENSORSTATE;
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600349 break;
350 }
George Liu1ec85d42020-02-12 16:05:32 +0800351 const DBusMapping& dbusMapping = dbusMappings[currState];
352 const StatestoDbusVal& dbusValToMap = dbusValMaps[currState];
353
354 if (stateField[currState].set_request == PLDM_REQUEST_SET)
355 {
356 try
357 {
358 dBusIntf.setDbusProperty(
359 dbusMapping,
360 dbusValToMap.at(
361 stateField[currState].effecter_state));
362 }
363 catch (const std::exception& e)
364 {
365 std::cerr
366 << "Error setting property, ERROR=" << e.what()
367 << " PROPERTY=" << dbusMapping.propertyName
368 << " INTERFACE="
369 << dbusMapping.interface << " PATH="
370 << dbusMapping.objectPath << "\n";
371 return PLDM_ERROR;
372 }
373 }
374 uint8_t* nextState =
375 reinterpret_cast<uint8_t*>(states) +
376 sizeof(state_effecter_possible_states) -
377 sizeof(states->states) +
378 (states->possible_states_size * sizeof(states->states));
379 states = reinterpret_cast<state_effecter_possible_states*>(
380 nextState);
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600381 }
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600382 }
George Liu1ec85d42020-02-12 16:05:32 +0800383 catch (const std::out_of_range& e)
384 {
385 std::cerr << "the effecterId does not exist. effecter id: "
386 << effecterId << e.what() << '\n';
387 }
388
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600389 return rc;
390 }
Deepak Kodihallic682fe22020-03-04 00:42:54 -0600391
392 private:
393 pdr_utils::Repo pdrRepo;
394 uint16_t nextEffecterId{};
George Liu1ec85d42020-02-12 16:05:32 +0800395 DbusObjMaps dbusObjMaps{};
Pavithra Barithaya51efaf82020-04-02 02:42:27 -0500396 HostPDRHandler* hostPDRHandler;
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600397};
398
399} // namespace platform
Deepak Kodihalli557dfb02019-05-12 13:11:17 +0530400} // namespace responder
401} // namespace pldm