blob: a435dcafe69558df39e209236c999b7df4007f74 [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
Deepak Kodihallibc669f12019-11-28 08:52:07 -060043class Handler : public CmdHandler
Sampa Misraa2fa0702019-05-31 01:28:55 -050044{
Deepak Kodihallibc669f12019-11-28 08:52:07 -060045 public:
Tom Joseph56e45c52020-03-16 10:01:45 +053046 Handler(const std::string& dir, pldm_pdr* repo,
47 const std::optional<EventMap>& addOnHandlersMap = std::nullopt) :
48 pdrRepo(repo)
Sampa Misraa2fa0702019-05-31 01:28:55 -050049 {
Deepak Kodihallic682fe22020-03-04 00:42:54 -060050 generate(dir, pdrRepo);
51
Deepak Kodihallibc669f12019-11-28 08:52:07 -060052 handlers.emplace(PLDM_GET_PDR,
53 [this](const pldm_msg* request, size_t payloadLength) {
54 return this->getPDR(request, payloadLength);
55 });
56 handlers.emplace(PLDM_SET_STATE_EFFECTER_STATES,
57 [this](const pldm_msg* request, size_t payloadLength) {
58 return this->setStateEffecterStates(request,
59 payloadLength);
60 });
Tom Joseph56e45c52020-03-16 10:01:45 +053061 handlers.emplace(PLDM_PLATFORM_EVENT_MESSAGE,
62 [this](const pldm_msg* request, size_t payloadLength) {
63 return this->platformEventMessage(request,
64 payloadLength);
65 });
66
67 // Default handler for PLDM Events
68 eventHandlers[PLDM_SENSOR_EVENT].emplace_back(
69 [this](const pldm_msg* request, size_t payloadLength,
70 uint8_t formatVersion, uint8_t tid, size_t eventDataOffset) {
71 return this->sensorEvent(request, payloadLength, formatVersion,
72 tid, eventDataOffset);
73 });
74
75 // Additional OEM event handlers for PLDM events, append it to the
76 // standard handlers
77 if (addOnHandlersMap)
78 {
79 auto addOnHandlers = addOnHandlersMap.value();
80 for (EventMap::iterator iter = addOnHandlers.begin();
81 iter != addOnHandlers.end(); ++iter)
82 {
83 auto search = eventHandlers.find(iter->first);
84 if (search != eventHandlers.end())
85 {
86 search->second.insert(std::end(search->second),
87 std::begin(iter->second),
88 std::end(iter->second));
89 }
90 else
91 {
92 eventHandlers.emplace(iter->first, iter->second);
93 }
94 }
95 }
Sampa Misraa2fa0702019-05-31 01:28:55 -050096 }
97
George Liu1ec85d42020-02-12 16:05:32 +080098 pdr_utils::Repo& getRepo()
Deepak Kodihallic682fe22020-03-04 00:42:54 -060099 {
George Liu1ec85d42020-02-12 16:05:32 +0800100 return this->pdrRepo;
Deepak Kodihallic682fe22020-03-04 00:42:54 -0600101 }
102
George Liu1ec85d42020-02-12 16:05:32 +0800103 /** @brief Add D-Bus mapping and value mapping(stateId to D-Bus) for the
104 * effecterId. If the same id is added, the previous dbusObjs will
105 * be "over-written".
106 *
107 * @param[in] effecterId - effecter id
108 * @param[in] dbusObj - list of D-Bus object structure and list of D-Bus
109 * property value to attribute value
110 */
George Liua2870722020-02-11 11:09:30 +0800111 void addDbusObjMaps(
112 uint16_t effecterId,
113 std::tuple<pdr_utils::DbusMappings, pdr_utils::DbusValMaps> dbusObj);
George Liu1ec85d42020-02-12 16:05:32 +0800114
115 /** @brief Retrieve an effecter id -> D-Bus objects mapping
116 *
117 * @param[in] effecterId - effecter id
118 *
George Liua2870722020-02-11 11:09:30 +0800119 * @return std::tuple<pdr_utils::DbusMappings, pdr_utils::DbusValMaps> -
120 * list of D-Bus object structure and list of D-Bus property value
121 * to attribute value
George Liu1ec85d42020-02-12 16:05:32 +0800122 */
George Liua2870722020-02-11 11:09:30 +0800123 const std::tuple<pdr_utils::DbusMappings, pdr_utils::DbusValMaps>&
George Liu1ec85d42020-02-12 16:05:32 +0800124 getDbusObjMaps(uint16_t effecterId) const;
Deepak Kodihallic682fe22020-03-04 00:42:54 -0600125
126 uint16_t getNextEffecterId()
127 {
128 return ++nextEffecterId;
129 }
130
131 /** @brief Parse PDR JSONs and build PDR repository
132 *
133 * @param[in] dir - directory housing platform specific PDR JSON files
134 * @param[in] repo - instance of concrete implementation of Repo
135 */
136 void generate(const std::string& dir, Repo& repo);
137
138 /** @brief Parse PDR JSONs and build state effecter PDR repository
139 *
140 * @param[in] json - platform specific PDR JSON files
141 * @param[in] repo - instance of state effecter implementation of Repo
142 */
143 void generateStateEffecterRepo(const Json& json, Repo& repo);
144
Tom Joseph56e45c52020-03-16 10:01:45 +0530145 /** @brief map of PLDM event type to EventHandlers
146 *
147 */
148 EventMap eventHandlers;
149
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600150 /** @brief Handler for GetPDR
151 *
152 * @param[in] request - Request message payload
153 * @param[in] payloadLength - Request payload length
154 * @param[out] Response - Response message written here
155 */
156 Response getPDR(const pldm_msg* request, size_t payloadLength);
Sampa Misraa2fa0702019-05-31 01:28:55 -0500157
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600158 /** @brief Handler for setStateEffecterStates
159 *
160 * @param[in] request - Request message
161 * @param[in] payloadLength - Request payload length
162 * @return Response - PLDM Response message
163 */
164 Response setStateEffecterStates(const pldm_msg* request,
165 size_t payloadLength);
166
Tom Joseph56e45c52020-03-16 10:01:45 +0530167 /** @brief Handler for PlatformEventMessage
168 *
169 * @param[in] request - Request message
170 * @param[in] payloadLength - Request payload length
171 * @return Response - PLDM Response message
172 */
173 Response platformEventMessage(const pldm_msg* request,
174 size_t payloadLength);
175
176 /** @brief Handler for event class Sensor event
177 *
178 * @param[in] request - Request message
179 * @param[in] payloadLength - Request payload length
180 * @param[in] formatVersion - Version of the event format
181 * @param[in] tid - Terminus ID of the event's originator
182 * @param[in] eventDataOffset - Offset of the event data in the request
183 * message
184 * @return PLDM completion code
185 */
186 int sensorEvent(const pldm_msg* request, size_t payloadLength,
187 uint8_t formatVersion, uint8_t tid, size_t eventDataOffset);
188
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600189 /** @brief Function to set the effecter requested by pldm requester
190 * @param[in] dBusIntf - The interface object
191 * @param[in] effecterId - Effecter ID sent by the requester to act on
192 * @param[in] stateField - The state field data for each of the states,
193 * equal to composite effecter count in number
194 * @return - Success or failure in setting the states. Returns failure in
195 * terms of PLDM completion codes if atleast one state fails to be set
196 */
197 template <class DBusInterface>
198 int setStateEffecterStatesHandler(
Deepak Kodihallic682fe22020-03-04 00:42:54 -0600199 const DBusInterface& dBusIntf, uint16_t effecterId,
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600200 const std::vector<set_effecter_state_field>& stateField)
Sampa Misraa2fa0702019-05-31 01:28:55 -0500201 {
George Liue53193f2020-02-24 09:23:26 +0800202 using namespace pldm::responder::pdr;
George Liu1e44c732020-02-28 20:20:06 +0800203 using namespace pldm::utils;
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600204 using StateSetNum = uint8_t;
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600205
206 state_effecter_possible_states* states = nullptr;
207 pldm_state_effecter_pdr* pdr = nullptr;
208 uint8_t compEffecterCnt = stateField.size();
George Liu1ec85d42020-02-12 16:05:32 +0800209
210 std::unique_ptr<pldm_pdr, decltype(&pldm_pdr_destroy)>
211 stateEffecterPdrRepo(pldm_pdr_init(), pldm_pdr_destroy);
212 Repo stateEffecterPDRs(stateEffecterPdrRepo.get());
213 getRepoByType(pdrRepo, stateEffecterPDRs, PLDM_STATE_EFFECTER_PDR);
214 if (stateEffecterPDRs.empty())
215 {
216 std::cerr << "Failed to get record by PDR type\n";
217 return PLDM_PLATFORM_INVALID_EFFECTER_ID;
218 }
219
George Liue53193f2020-02-24 09:23:26 +0800220 PdrEntry pdrEntry{};
George Liu1ec85d42020-02-12 16:05:32 +0800221 auto pdrRecord = stateEffecterPDRs.getFirstRecord(pdrEntry);
George Liue53193f2020-02-24 09:23:26 +0800222 while (pdrRecord)
223 {
224 pdr = reinterpret_cast<pldm_state_effecter_pdr*>(pdrEntry.data);
225 if (pdr->effecter_id != effecterId)
Sampa Misraa2fa0702019-05-31 01:28:55 -0500226 {
George Liue53193f2020-02-24 09:23:26 +0800227 pdr = nullptr;
George Liu1ec85d42020-02-12 16:05:32 +0800228 pdrRecord =
229 stateEffecterPDRs.getNextRecord(pdrRecord, pdrEntry);
George Liue53193f2020-02-24 09:23:26 +0800230 continue;
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600231 }
George Liue53193f2020-02-24 09:23:26 +0800232
233 states = reinterpret_cast<state_effecter_possible_states*>(
234 pdr->possible_states);
235 if (compEffecterCnt > pdr->composite_effecter_count)
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600236 {
George Liue53193f2020-02-24 09:23:26 +0800237 std::cerr << "The requester sent wrong composite effecter"
238 << " count for the effecter, EFFECTER_ID="
239 << effecterId << "COMP_EFF_CNT=" << compEffecterCnt
240 << "\n";
241 return PLDM_ERROR_INVALID_DATA;
Sampa Misraa2fa0702019-05-31 01:28:55 -0500242 }
George Liue53193f2020-02-24 09:23:26 +0800243 break;
244 }
245
246 if (!pdr)
247 {
248 return PLDM_PLATFORM_INVALID_EFFECTER_ID;
Sampa Misraa2fa0702019-05-31 01:28:55 -0500249 }
Sampa Misraa2fa0702019-05-31 01:28:55 -0500250
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600251 int rc = PLDM_SUCCESS;
George Liu1ec85d42020-02-12 16:05:32 +0800252 try
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600253 {
George Liu1ec85d42020-02-12 16:05:32 +0800254 const auto& [dbusMappings, dbusValMaps] =
255 dbusObjMaps.at(effecterId);
256 for (uint8_t currState = 0; currState < compEffecterCnt;
257 ++currState)
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600258 {
George Liu1ec85d42020-02-12 16:05:32 +0800259 std::vector<StateSetNum> allowed{};
260 // computation is based on table 79 from DSP0248 v1.1.1
261 uint8_t bitfieldIndex =
262 stateField[currState].effecter_state / 8;
263 uint8_t bit =
264 stateField[currState].effecter_state - (8 * bitfieldIndex);
265 if (states->possible_states_size < bitfieldIndex ||
266 !(states->states[bitfieldIndex].byte & (1 << bit)))
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600267 {
George Liu1ec85d42020-02-12 16:05:32 +0800268 std::cerr
269 << "Invalid state set value, EFFECTER_ID=" << effecterId
270 << " VALUE=" << stateField[currState].effecter_state
271 << " COMPOSITE_EFFECTER_ID=" << currState
272 << " DBUS_PATH=" << dbusMappings[currState].objectPath
273 << "\n";
274 rc = PLDM_PLATFORM_SET_EFFECTER_UNSUPPORTED_SENSORSTATE;
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600275 break;
276 }
George Liu1ec85d42020-02-12 16:05:32 +0800277 const DBusMapping& dbusMapping = dbusMappings[currState];
278 const StatestoDbusVal& dbusValToMap = dbusValMaps[currState];
279
280 if (stateField[currState].set_request == PLDM_REQUEST_SET)
281 {
282 try
283 {
284 dBusIntf.setDbusProperty(
285 dbusMapping,
286 dbusValToMap.at(
287 stateField[currState].effecter_state));
288 }
289 catch (const std::exception& e)
290 {
291 std::cerr
292 << "Error setting property, ERROR=" << e.what()
293 << " PROPERTY=" << dbusMapping.propertyName
294 << " INTERFACE="
295 << dbusMapping.interface << " PATH="
296 << dbusMapping.objectPath << "\n";
297 return PLDM_ERROR;
298 }
299 }
300 uint8_t* nextState =
301 reinterpret_cast<uint8_t*>(states) +
302 sizeof(state_effecter_possible_states) -
303 sizeof(states->states) +
304 (states->possible_states_size * sizeof(states->states));
305 states = reinterpret_cast<state_effecter_possible_states*>(
306 nextState);
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600307 }
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600308 }
George Liu1ec85d42020-02-12 16:05:32 +0800309 catch (const std::out_of_range& e)
310 {
311 std::cerr << "the effecterId does not exist. effecter id: "
312 << effecterId << e.what() << '\n';
313 }
314
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600315 return rc;
316 }
Deepak Kodihallic682fe22020-03-04 00:42:54 -0600317
318 private:
319 pdr_utils::Repo pdrRepo;
320 uint16_t nextEffecterId{};
George Liu1ec85d42020-02-12 16:05:32 +0800321 DbusObjMaps dbusObjMaps{};
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600322};
323
324} // namespace platform
Deepak Kodihalli557dfb02019-05-12 13:11:17 +0530325} // namespace responder
326} // namespace pldm