blob: 696434bea480083731547d208e05c591dd59cc78 [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"
Sampa Misraa2fa0702019-05-31 01:28:55 -05006#include "libpldmresponder/pdr.hpp"
George Liue53193f2020-02-24 09:23:26 +08007#include "libpldmresponder/pdr_utils.hpp"
George Liu83409572019-12-24 18:42:54 +08008#include "utils.hpp"
Sampa Misraa2fa0702019-05-31 01:28:55 -05009
Deepak Kodihalli557dfb02019-05-12 13:11:17 +053010#include <stdint.h>
11
Sampa Misraa2fa0702019-05-31 01:28:55 -050012#include <map>
Deepak Kodihalli557dfb02019-05-12 13:11:17 +053013
14#include "libpldm/platform.h"
Sampa Misraa2fa0702019-05-31 01:28:55 -050015#include "libpldm/states.h"
Deepak Kodihalli557dfb02019-05-12 13:11:17 +053016
17namespace pldm
18{
Deepak Kodihalli557dfb02019-05-12 13:11:17 +053019namespace responder
20{
Sampa Misraa2fa0702019-05-31 01:28:55 -050021namespace platform
22{
23
George Liu1ec85d42020-02-12 16:05:32 +080024using namespace pldm::utils;
25using namespace pldm::responder::pdr_utils;
26
George Liua2870722020-02-11 11:09:30 +080027using generatePDR =
28 std::function<void(const Json& json, pdr_utils::RepoInterface& repo)>;
29
George Liu1ec85d42020-02-12 16:05:32 +080030using EffecterId = uint16_t;
George Liua2870722020-02-11 11:09:30 +080031using DbusObjMaps =
32 std::map<EffecterId,
33 std::tuple<pdr_utils::DbusMappings, pdr_utils::DbusValMaps>>;
Tom Joseph56e45c52020-03-16 10:01:45 +053034using DbusPath = std::string;
35using EffecterObjs = std::vector<DbusPath>;
36using EventType = uint8_t;
37using EventHandler = std::function<int(
38 const pldm_msg* request, size_t payloadLength, uint8_t formatVersion,
39 uint8_t tid, size_t eventDataOffset)>;
40using EventHandlers = std::vector<EventHandler>;
41using EventMap = std::map<EventType, EventHandlers>;
Deepak Kodihallic682fe22020-03-04 00:42:54 -060042
Zahed Hossain75330f32020-03-24 02:15:03 -050043// EventEntry = <uint8_t> - EventState <uint8_t> - SensorOffset <uint16_t> -
44// SensorID
45using EventEntry = uint32_t;
46struct DBusInfo
47{
48 pldm::utils::DBusMapping dBusValues;
49 pldm::utils::PropertyValue dBusPropertyValue;
50};
51
Deepak Kodihallibc669f12019-11-28 08:52:07 -060052class Handler : public CmdHandler
Sampa Misraa2fa0702019-05-31 01:28:55 -050053{
Deepak Kodihallibc669f12019-11-28 08:52:07 -060054 public:
Tom Joseph56e45c52020-03-16 10:01:45 +053055 Handler(const std::string& dir, pldm_pdr* repo,
56 const std::optional<EventMap>& addOnHandlersMap = std::nullopt) :
57 pdrRepo(repo)
Sampa Misraa2fa0702019-05-31 01:28:55 -050058 {
Deepak Kodihallic682fe22020-03-04 00:42:54 -060059 generate(dir, pdrRepo);
60
Deepak Kodihallibc669f12019-11-28 08:52:07 -060061 handlers.emplace(PLDM_GET_PDR,
62 [this](const pldm_msg* request, size_t payloadLength) {
63 return this->getPDR(request, payloadLength);
64 });
65 handlers.emplace(PLDM_SET_STATE_EFFECTER_STATES,
66 [this](const pldm_msg* request, size_t payloadLength) {
67 return this->setStateEffecterStates(request,
68 payloadLength);
69 });
Tom Joseph56e45c52020-03-16 10:01:45 +053070 handlers.emplace(PLDM_PLATFORM_EVENT_MESSAGE,
71 [this](const pldm_msg* request, size_t payloadLength) {
72 return this->platformEventMessage(request,
73 payloadLength);
74 });
75
76 // Default handler for PLDM Events
77 eventHandlers[PLDM_SENSOR_EVENT].emplace_back(
78 [this](const pldm_msg* request, size_t payloadLength,
79 uint8_t formatVersion, uint8_t tid, size_t eventDataOffset) {
80 return this->sensorEvent(request, payloadLength, formatVersion,
81 tid, eventDataOffset);
82 });
83
84 // Additional OEM event handlers for PLDM events, append it to the
85 // standard handlers
86 if (addOnHandlersMap)
87 {
88 auto addOnHandlers = addOnHandlersMap.value();
89 for (EventMap::iterator iter = addOnHandlers.begin();
90 iter != addOnHandlers.end(); ++iter)
91 {
92 auto search = eventHandlers.find(iter->first);
93 if (search != eventHandlers.end())
94 {
95 search->second.insert(std::end(search->second),
96 std::begin(iter->second),
97 std::end(iter->second));
98 }
99 else
100 {
101 eventHandlers.emplace(iter->first, iter->second);
102 }
103 }
104 }
Sampa Misraa2fa0702019-05-31 01:28:55 -0500105 }
106
George Liu1ec85d42020-02-12 16:05:32 +0800107 pdr_utils::Repo& getRepo()
Deepak Kodihallic682fe22020-03-04 00:42:54 -0600108 {
George Liu1ec85d42020-02-12 16:05:32 +0800109 return this->pdrRepo;
Deepak Kodihallic682fe22020-03-04 00:42:54 -0600110 }
111
George Liu1ec85d42020-02-12 16:05:32 +0800112 /** @brief Add D-Bus mapping and value mapping(stateId to D-Bus) for the
113 * effecterId. If the same id is added, the previous dbusObjs will
114 * be "over-written".
115 *
116 * @param[in] effecterId - effecter id
117 * @param[in] dbusObj - list of D-Bus object structure and list of D-Bus
118 * property value to attribute value
119 */
George Liua2870722020-02-11 11:09:30 +0800120 void addDbusObjMaps(
121 uint16_t effecterId,
122 std::tuple<pdr_utils::DbusMappings, pdr_utils::DbusValMaps> dbusObj);
George Liu1ec85d42020-02-12 16:05:32 +0800123
124 /** @brief Retrieve an effecter id -> D-Bus objects mapping
125 *
126 * @param[in] effecterId - effecter id
127 *
George Liua2870722020-02-11 11:09:30 +0800128 * @return std::tuple<pdr_utils::DbusMappings, pdr_utils::DbusValMaps> -
129 * list of D-Bus object structure and list of D-Bus property value
130 * to attribute value
George Liu1ec85d42020-02-12 16:05:32 +0800131 */
George Liua2870722020-02-11 11:09:30 +0800132 const std::tuple<pdr_utils::DbusMappings, pdr_utils::DbusValMaps>&
George Liu1ec85d42020-02-12 16:05:32 +0800133 getDbusObjMaps(uint16_t effecterId) const;
Deepak Kodihallic682fe22020-03-04 00:42:54 -0600134
135 uint16_t getNextEffecterId()
136 {
137 return ++nextEffecterId;
138 }
139
140 /** @brief Parse PDR JSONs and build PDR repository
141 *
142 * @param[in] dir - directory housing platform specific PDR JSON files
143 * @param[in] repo - instance of concrete implementation of Repo
144 */
145 void generate(const std::string& dir, Repo& repo);
146
147 /** @brief Parse PDR JSONs and build state effecter PDR repository
148 *
149 * @param[in] json - platform specific PDR JSON files
150 * @param[in] repo - instance of state effecter implementation of Repo
151 */
152 void generateStateEffecterRepo(const Json& json, Repo& repo);
153
Tom Joseph56e45c52020-03-16 10:01:45 +0530154 /** @brief map of PLDM event type to EventHandlers
155 *
156 */
157 EventMap eventHandlers;
158
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600159 /** @brief Handler for GetPDR
160 *
161 * @param[in] request - Request message payload
162 * @param[in] payloadLength - Request payload length
163 * @param[out] Response - Response message written here
164 */
165 Response getPDR(const pldm_msg* request, size_t payloadLength);
Sampa Misraa2fa0702019-05-31 01:28:55 -0500166
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600167 /** @brief Handler for setStateEffecterStates
168 *
169 * @param[in] request - Request message
170 * @param[in] payloadLength - Request payload length
171 * @return Response - PLDM Response message
172 */
173 Response setStateEffecterStates(const pldm_msg* request,
174 size_t payloadLength);
175
Tom Joseph56e45c52020-03-16 10:01:45 +0530176 /** @brief Handler for PlatformEventMessage
177 *
178 * @param[in] request - Request message
179 * @param[in] payloadLength - Request payload length
180 * @return Response - PLDM Response message
181 */
182 Response platformEventMessage(const pldm_msg* request,
183 size_t payloadLength);
184
185 /** @brief Handler for event class Sensor event
186 *
187 * @param[in] request - Request message
188 * @param[in] payloadLength - Request payload length
189 * @param[in] formatVersion - Version of the event format
190 * @param[in] tid - Terminus ID of the event's originator
191 * @param[in] eventDataOffset - Offset of the event data in the request
192 * message
193 * @return PLDM completion code
194 */
195 int sensorEvent(const pldm_msg* request, size_t payloadLength,
196 uint8_t formatVersion, uint8_t tid, size_t eventDataOffset);
197
Zahed Hossain75330f32020-03-24 02:15:03 -0500198 /** @brief Handler for setting Sensor event data
199 *
200 * @param[in] sensorId - sensorID value of the sensor
201 * @param[in] sensorOffset - Identifies which state sensor within a
202 * composite state sensor the event is being returned for
203 * @param[in] eventState - The event state value from the state change that
204 * triggered the event message
205 * @return PLDM completion code
206 */
207 int setSensorEventData(uint16_t sensorId, uint8_t sensorOffset,
208 uint8_t eventState);
209
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600210 /** @brief Function to set the effecter requested by pldm requester
211 * @param[in] dBusIntf - The interface object
212 * @param[in] effecterId - Effecter ID sent by the requester to act on
213 * @param[in] stateField - The state field data for each of the states,
214 * equal to composite effecter count in number
215 * @return - Success or failure in setting the states. Returns failure in
216 * terms of PLDM completion codes if atleast one state fails to be set
217 */
218 template <class DBusInterface>
219 int setStateEffecterStatesHandler(
Deepak Kodihallic682fe22020-03-04 00:42:54 -0600220 const DBusInterface& dBusIntf, uint16_t effecterId,
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600221 const std::vector<set_effecter_state_field>& stateField)
Sampa Misraa2fa0702019-05-31 01:28:55 -0500222 {
George Liue53193f2020-02-24 09:23:26 +0800223 using namespace pldm::responder::pdr;
George Liu1e44c732020-02-28 20:20:06 +0800224 using namespace pldm::utils;
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600225 using StateSetNum = uint8_t;
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600226
227 state_effecter_possible_states* states = nullptr;
228 pldm_state_effecter_pdr* pdr = nullptr;
229 uint8_t compEffecterCnt = stateField.size();
George Liu1ec85d42020-02-12 16:05:32 +0800230
231 std::unique_ptr<pldm_pdr, decltype(&pldm_pdr_destroy)>
232 stateEffecterPdrRepo(pldm_pdr_init(), pldm_pdr_destroy);
233 Repo stateEffecterPDRs(stateEffecterPdrRepo.get());
234 getRepoByType(pdrRepo, stateEffecterPDRs, PLDM_STATE_EFFECTER_PDR);
235 if (stateEffecterPDRs.empty())
236 {
237 std::cerr << "Failed to get record by PDR type\n";
238 return PLDM_PLATFORM_INVALID_EFFECTER_ID;
239 }
240
George Liue53193f2020-02-24 09:23:26 +0800241 PdrEntry pdrEntry{};
George Liu1ec85d42020-02-12 16:05:32 +0800242 auto pdrRecord = stateEffecterPDRs.getFirstRecord(pdrEntry);
George Liue53193f2020-02-24 09:23:26 +0800243 while (pdrRecord)
244 {
245 pdr = reinterpret_cast<pldm_state_effecter_pdr*>(pdrEntry.data);
246 if (pdr->effecter_id != effecterId)
Sampa Misraa2fa0702019-05-31 01:28:55 -0500247 {
George Liue53193f2020-02-24 09:23:26 +0800248 pdr = nullptr;
George Liu1ec85d42020-02-12 16:05:32 +0800249 pdrRecord =
250 stateEffecterPDRs.getNextRecord(pdrRecord, pdrEntry);
George Liue53193f2020-02-24 09:23:26 +0800251 continue;
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600252 }
George Liue53193f2020-02-24 09:23:26 +0800253
254 states = reinterpret_cast<state_effecter_possible_states*>(
255 pdr->possible_states);
256 if (compEffecterCnt > pdr->composite_effecter_count)
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600257 {
George Liue53193f2020-02-24 09:23:26 +0800258 std::cerr << "The requester sent wrong composite effecter"
259 << " count for the effecter, EFFECTER_ID="
260 << effecterId << "COMP_EFF_CNT=" << compEffecterCnt
261 << "\n";
262 return PLDM_ERROR_INVALID_DATA;
Sampa Misraa2fa0702019-05-31 01:28:55 -0500263 }
George Liue53193f2020-02-24 09:23:26 +0800264 break;
265 }
266
267 if (!pdr)
268 {
269 return PLDM_PLATFORM_INVALID_EFFECTER_ID;
Sampa Misraa2fa0702019-05-31 01:28:55 -0500270 }
Sampa Misraa2fa0702019-05-31 01:28:55 -0500271
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600272 int rc = PLDM_SUCCESS;
George Liu1ec85d42020-02-12 16:05:32 +0800273 try
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600274 {
George Liu1ec85d42020-02-12 16:05:32 +0800275 const auto& [dbusMappings, dbusValMaps] =
276 dbusObjMaps.at(effecterId);
277 for (uint8_t currState = 0; currState < compEffecterCnt;
278 ++currState)
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600279 {
George Liu1ec85d42020-02-12 16:05:32 +0800280 std::vector<StateSetNum> allowed{};
281 // computation is based on table 79 from DSP0248 v1.1.1
282 uint8_t bitfieldIndex =
283 stateField[currState].effecter_state / 8;
284 uint8_t bit =
285 stateField[currState].effecter_state - (8 * bitfieldIndex);
286 if (states->possible_states_size < bitfieldIndex ||
287 !(states->states[bitfieldIndex].byte & (1 << bit)))
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600288 {
George Liu1ec85d42020-02-12 16:05:32 +0800289 std::cerr
290 << "Invalid state set value, EFFECTER_ID=" << effecterId
291 << " VALUE=" << stateField[currState].effecter_state
292 << " COMPOSITE_EFFECTER_ID=" << currState
293 << " DBUS_PATH=" << dbusMappings[currState].objectPath
294 << "\n";
295 rc = PLDM_PLATFORM_SET_EFFECTER_UNSUPPORTED_SENSORSTATE;
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600296 break;
297 }
George Liu1ec85d42020-02-12 16:05:32 +0800298 const DBusMapping& dbusMapping = dbusMappings[currState];
299 const StatestoDbusVal& dbusValToMap = dbusValMaps[currState];
300
301 if (stateField[currState].set_request == PLDM_REQUEST_SET)
302 {
303 try
304 {
305 dBusIntf.setDbusProperty(
306 dbusMapping,
307 dbusValToMap.at(
308 stateField[currState].effecter_state));
309 }
310 catch (const std::exception& e)
311 {
312 std::cerr
313 << "Error setting property, ERROR=" << e.what()
314 << " PROPERTY=" << dbusMapping.propertyName
315 << " INTERFACE="
316 << dbusMapping.interface << " PATH="
317 << dbusMapping.objectPath << "\n";
318 return PLDM_ERROR;
319 }
320 }
321 uint8_t* nextState =
322 reinterpret_cast<uint8_t*>(states) +
323 sizeof(state_effecter_possible_states) -
324 sizeof(states->states) +
325 (states->possible_states_size * sizeof(states->states));
326 states = reinterpret_cast<state_effecter_possible_states*>(
327 nextState);
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600328 }
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600329 }
George Liu1ec85d42020-02-12 16:05:32 +0800330 catch (const std::out_of_range& e)
331 {
332 std::cerr << "the effecterId does not exist. effecter id: "
333 << effecterId << e.what() << '\n';
334 }
335
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600336 return rc;
337 }
Deepak Kodihallic682fe22020-03-04 00:42:54 -0600338
339 private:
340 pdr_utils::Repo pdrRepo;
341 uint16_t nextEffecterId{};
George Liu1ec85d42020-02-12 16:05:32 +0800342 DbusObjMaps dbusObjMaps{};
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600343};
344
345} // namespace platform
Deepak Kodihalli557dfb02019-05-12 13:11:17 +0530346} // namespace responder
347} // namespace pldm